精华内容
下载资源
问答
  • 西华大学实验报告 西华大学实验报告 PAGE PAGE # 西华大学实验报告 第 组 ...年级/专业/班 课程名称 课程代码 实验项目名称 实验七数据库编程 项目代码 指导教师 项目学分 实验目的 1 了解数据库管理数据库数据模型概
  • 关于编程语言中的时间格式和关系型数据中的中时间格式问题的转化一直都是个简单而又不得不权衡的问题,这牵扯到数据库设计和SQL编程和应用程序中时间格式数据的处理的编程,两者总能够交缠在一起。  关于Java中的...
  • Qt数据库编程

    千次阅读 2018-10-25 15:14:18
    Qt使用数据库sqlite 版本说明 版本 作者 日期 备注 0.1 loon 2018.10.25 初稿 目录 文章目录Qt使用数据库sqlite版本说明目录一、需求和目的二、使用说明1、Qt 5.6.0的数据库操作类...

    Qt数据库编程


    版本说明

    版本作者日期备注
    0.1loon2018.10.25初稿

    目录

    一、需求和目的

    数据库在某些情况下,相对于文件操作更加方便,软件在某些情况下对于数据库也是必不可少的,因此,我们有必要了解和学习在Qt开发中如何使用数据库,由于sqlite文件数据库较为方便且Qt默认带有其引擎,所以以下总结基于sqlite。

    二、使用说明

    我们前面探索学习Qt时提到过帮助文档,那么如何使用Qt的SQL我们就来试一下,在Qt creator的帮助中搜索SQL,找到SQL Programming,里面提到一些建议和Database Classes以及这些类的用处:
    在这里插入图片描述

    1、Qt 5.6.0的数据库操作类:

    These classes provide access to SQL databases.

    QSqlContains miscellaneous identifiers used throughout the Qt SQL module
    QSqlDatabaseRepresents a connection to a database
    QSqlDriverAbstract base class for accessing specific SQL databases
    QSqlDriverCreatorTemplate class that provides a SQL driver factory for a specific driver type
    QSqlDriverCreatorBaseThe base class for SQL driver factories
    QSqlErrorSQL database error information
    QSqlFieldManipulates the fields in SQL database tables and views
    QSqlIndexFunctions to manipulate and describe database indexes
    QSqlQueryMeans of executing and manipulating SQL statements
    QSqlQueryModelRead-only data model for SQL result sets
    QSqlRecordEncapsulates a database record
    QSqlRelationalTableModelEditable data model for a single database table, with foreign key support
    QSqlResultAbstract interface for accessing data from specific SQL databases
    QSqlTableModelEditable data model for a single database table

    这些类包括在以下三层中:Driver Layer、SQL API Layer、User Interface Layer。

    2、Driver Layer

    驱动层是SQL api和特殊数据库之间的低等级的桥梁,不同的数据库其SQL api可能会有所不同,其支持的数据库种类包括:

    QDB2IBM DB2 (version 7.1 and above)
    QIBASEBorland InterBase
    QMYSQLMySQL
    QOCIOracle Call Interface Driver
    QODBCOpen Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databases
    QPSQLPostgreSQL (versions 7.3 and above)
    QSQLITE2SQLite version 2
    QSQLITESQLite version 3
    QTDSSybase Adaptive Server Note: obsolete from Qt 4.7

    我们要用的就是QSQLITE,支持SQLite3及其以上版本。关于如何编译对应的数据库,以插件形式加入到Qt,这里就不多说了,后续需要的话可以单独做个总结,这都是在帮助文档中有的。

    在这里插入图片描述

    3、SQL API Layer

    These classes provide access to databases. Connections are made using the QSqlDatabase class. Database interaction is achieved by using the QSqlQuery class. In addition to QSqlDatabase and QSqlQuery, the SQL API layer is supported by QSqlError, QSqlField, QSqlIndex, and QSqlRecord.
    这些类提供对数据库的访问。使用QSqlDatabase类建立连接。数据库交互是通过使用QSqlQuery类实现的。除了QSqlDatabase和QSqlQuery之外,SQL API层还支持QSqlError、QSqlField、QSqlIndex和QSqlRecord。

    4、User Interface Layer

    These classes link the data from a database to data-aware widgets. They include QSqlQueryModel, QSqlTableModel, and QSqlRelationalTableModel. These classes are designed to work with Qt’s model/view framework.
    Note that a QCoreApplication object must be instantiated before using any of these classes.
    这些类将数据从数据库链接到支持数据的小部件。它们包括QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel。这些类被设计用于Qt的模型/视图框架。
    注意,QCoreApplication对象必须在使用这些类之前实例化。

    5、Qt5.6.0 SQL programming使用流程

    找到SQL programming,了解Qt如何进行SQL编程;
    之后就是Connecting to Databases,看到如何连接数据库;
    再接着 Executing SQL Statements,看如何执行sql语句;
    再接着 Using the SQL Model Classes,使用SQL模块类进行数据查询等;
    然后是Presenting Data in a Table View,将查询到的数据在表格视图中显示;
    最后是Creating Data-Aware Forms,创建数据感知形式,以提交表单的形式插入数据或修改数据后在界面上呈现出来。

    具体每一步在帮助中都描述的很清楚了,你只需要去阅读以下就可以了。

    三、阅读及分析示例

    OK,当你阅读完之后,我们再找个例子先大致看一下如何使用,就找Qt creator自带的,在示例中直接搜索SQL:

    在这里插入图片描述

    那么我们按照上面总结的流程去看一下每个例子,最后再自己写一个例子,看例子的过程中有不懂的API记得F1寻找帮助,这样的话,掌握Qt SQL Programming只是时间问题了。

    下面就以第一个例子Books来说一下:

    1、示例运行

    打开示例,第一次打开需要点击配置进行项目配置,然后就可以编译运行了,运行结果如下:

    在这里插入图片描述

    2、源码分析

    可以看到项目中有.pro工程文件、头文件、源文件、界面文件和资源。

    首先看books.pro

    TEMPLATE = app
    INCLUDEPATH += .
    
    HEADERS     = bookdelegate.h bookwindow.h initdb.h
    RESOURCES   = books.qrc
    SOURCES     = bookdelegate.cpp main.cpp bookwindow.cpp
    FORMS       = bookwindow.ui
    
    QT += sql widgets widgets
    
    target.path = $$[QT_INSTALL_EXAMPLES]/sql/books
    INSTALLS += target
    
    
    wince {
        CONFIG(debug, debug|release):sqlPlugins.files = $$QT_BUILD_TREE/plugins/sqldrivers/*d4.dll
        CONFIG(release, debug|release):sqlPlugins.files = $$QT_BUILD_TREE/plugins/sqldrivers/*[^d]4.dll
        sqlPlugins.path = sqldrivers
        INSTALLS += sqlPlugins
    }
    

    需要注意的时qmake需要添加sql,所以需要加上QT += sql,这个在Driver层中提到过,所以.pro中需要注意就是这个。

    然后从main.cpp开始看起:

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the demonstration applications of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:LGPL21$
    ** Commercial License Usage
    ** Licensees holding valid commercial Qt licenses may use this file in
    ** accordance with the commercial license agreement provided with the
    ** Software or, alternatively, in accordance with the terms contained in
    ** a written agreement between you and The Qt Company. For licensing terms
    ** and conditions see http://www.qt.io/terms-conditions. For further
    ** information use the contact form at http://www.qt.io/contact-us.
    **
    ** GNU Lesser General Public License Usage
    ** Alternatively, this file may be used under the terms of the GNU Lesser
    ** General Public License version 2.1 or version 3 as published by the Free
    ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
    ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
    ** following information to ensure the GNU Lesser General Public License
    ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
    ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    **
    ** As a special exception, The Qt Company gives you certain additional
    ** rights. These rights are described in The Qt Company LGPL Exception
    ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/
    
    #include "bookwindow.h"
    
    #include <QtWidgets>
    
    int main(int argc, char * argv[])
    {
        Q_INIT_RESOURCE(books);
    
        QApplication app(argc, argv);
    
        BookWindow win;
        win.show();
    
        return app.exec();
    }
    

    可以看到基类是widget,Q_INIT_RESOURCE(books)使用F1查看后发现是用来初始化资源文件books.qrc的。然后就是创建了win对象,那么我们接着去看BookWindow类吧。

    bookwindow.h:

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the demonstration applications of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:LGPL21$
    ** Commercial License Usage
    ** Licensees holding valid commercial Qt licenses may use this file in
    ** accordance with the commercial license agreement provided with the
    ** Software or, alternatively, in accordance with the terms contained in
    ** a written agreement between you and The Qt Company. For licensing terms
    ** and conditions see http://www.qt.io/terms-conditions. For further
    ** information use the contact form at http://www.qt.io/contact-us.
    **
    ** GNU Lesser General Public License Usage
    ** Alternatively, this file may be used under the terms of the GNU Lesser
    ** General Public License version 2.1 or version 3 as published by the Free
    ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
    ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
    ** following information to ensure the GNU Lesser General Public License
    ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
    ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    **
    ** As a special exception, The Qt Company gives you certain additional
    ** rights. These rights are described in The Qt Company LGPL Exception
    ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/
    
    #ifndef BOOKWINDOW_H
    #define BOOKWINDOW_H
    
    #include <QtWidgets>
    #include <QtSql>
    
    #include "ui_bookwindow.h"
    
    
    class BookWindow: public QMainWindow
    {
        Q_OBJECT
    public:
        BookWindow();
    
    private:
        void showError(const QSqlError &err);
        Ui::BookWindow ui;
        QSqlRelationalTableModel *model;
        int authorIdx, genreIdx;
    };
    
    #endif
    

    bookwindow.cpp:

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the demonstration applications of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:LGPL21$
    ** Commercial License Usage
    ** Licensees holding valid commercial Qt licenses may use this file in
    ** accordance with the commercial license agreement provided with the
    ** Software or, alternatively, in accordance with the terms contained in
    ** a written agreement between you and The Qt Company. For licensing terms
    ** and conditions see http://www.qt.io/terms-conditions. For further
    ** information use the contact form at http://www.qt.io/contact-us.
    **
    ** GNU Lesser General Public License Usage
    ** Alternatively, this file may be used under the terms of the GNU Lesser
    ** General Public License version 2.1 or version 3 as published by the Free
    ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
    ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
    ** following information to ensure the GNU Lesser General Public License
    ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
    ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    **
    ** As a special exception, The Qt Company gives you certain additional
    ** rights. These rights are described in The Qt Company LGPL Exception
    ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/
    
    #include "bookwindow.h"
    #include "bookdelegate.h"
    #include "initdb.h"
    
    #include <QtSql>
    
    BookWindow::BookWindow()
    {
        ui.setupUi(this);
    
        if (!QSqlDatabase::drivers().contains("QSQLITE"))
            QMessageBox::critical(this, "Unable to load database", "This demo needs the SQLITE driver");
    
        // initialize the database
        QSqlError err = initDb();
        if (err.type() != QSqlError::NoError) {
            showError(err);
            return;
        }
    
        // Create the data model
        model = new QSqlRelationalTableModel(ui.bookTable);
        model->setEditStrategy(QSqlTableModel::OnManualSubmit);
        model->setTable("books");
    
        // Remember the indexes of the columns
        authorIdx = model->fieldIndex("author");
        genreIdx = model->fieldIndex("genre");
    
        // Set the relations to the other database tables
        model->setRelation(authorIdx, QSqlRelation("authors", "id", "name"));
        model->setRelation(genreIdx, QSqlRelation("genres", "id", "name"));
    
        // Set the localized header captions
        model->setHeaderData(authorIdx, Qt::Horizontal, tr("Author Name"));
        model->setHeaderData(genreIdx, Qt::Horizontal, tr("Genre"));
        model->setHeaderData(model->fieldIndex("title"), Qt::Horizontal, tr("Title"));
        model->setHeaderData(model->fieldIndex("year"), Qt::Horizontal, tr("Year"));
        model->setHeaderData(model->fieldIndex("rating"), Qt::Horizontal, tr("Rating"));
    
        // Populate the model
        if (!model->select()) {
            showError(model->lastError());
            return;
        }
    
        // Set the model and hide the ID column
        ui.bookTable->setModel(model);
        ui.bookTable->setItemDelegate(new BookDelegate(ui.bookTable));
        ui.bookTable->setColumnHidden(model->fieldIndex("id"), true);
        ui.bookTable->setSelectionMode(QAbstractItemView::SingleSelection);
    
        // Initialize the Author combo box
        ui.authorEdit->setModel(model->relationModel(authorIdx));
        ui.authorEdit->setModelColumn(model->relationModel(authorIdx)->fieldIndex("name"));
    
        ui.genreEdit->setModel(model->relationModel(genreIdx));
        ui.genreEdit->setModelColumn(model->relationModel(genreIdx)->fieldIndex("name"));
    
        QDataWidgetMapper *mapper = new QDataWidgetMapper(this);
        mapper->setModel(model);
        mapper->setItemDelegate(new BookDelegate(this));
        mapper->addMapping(ui.titleEdit, model->fieldIndex("title"));
        mapper->addMapping(ui.yearEdit, model->fieldIndex("year"));
        mapper->addMapping(ui.authorEdit, authorIdx);
        mapper->addMapping(ui.genreEdit, genreIdx);
        mapper->addMapping(ui.ratingEdit, model->fieldIndex("rating"));
    
        connect(ui.bookTable->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
                mapper, SLOT(setCurrentModelIndex(QModelIndex)));
    
        ui.bookTable->setCurrentIndex(model->index(0, 0));
    }
    
    void BookWindow::showError(const QSqlError &err)
    {
        QMessageBox::critical(this, "Unable to initialize Database",
                    "Error initializing database: " + err.text());
    }
    

    分析一下其构造函数的流程:1、设置驱动,选择数据库类型;2、初始化数据库;3、创建数据模型;4、记录列号;5、设置到其它数据库表的关系;6、填充模型;7、设置模型并隐藏ID列 ;8、初始化作者组合框 。

    bookwindow.ui:

    在这里插入图片描述

    initdb.h:

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the demonstration applications of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:LGPL21$
    ** Commercial License Usage
    ** Licensees holding valid commercial Qt licenses may use this file in
    ** accordance with the commercial license agreement provided with the
    ** Software or, alternatively, in accordance with the terms contained in
    ** a written agreement between you and The Qt Company. For licensing terms
    ** and conditions see http://www.qt.io/terms-conditions. For further
    ** information use the contact form at http://www.qt.io/contact-us.
    **
    ** GNU Lesser General Public License Usage
    ** Alternatively, this file may be used under the terms of the GNU Lesser
    ** General Public License version 2.1 or version 3 as published by the Free
    ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
    ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
    ** following information to ensure the GNU Lesser General Public License
    ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
    ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    **
    ** As a special exception, The Qt Company gives you certain additional
    ** rights. These rights are described in The Qt Company LGPL Exception
    ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/
    
    #ifndef INITDB_H
    #define INITDB_H
    
    #include <QtSql>
    
    void addBook(QSqlQuery &q, const QString &title, int year, const QVariant &authorId,
                 const QVariant &genreId, int rating)
    {
        q.addBindValue(title);
        q.addBindValue(year);
        q.addBindValue(authorId);
        q.addBindValue(genreId);
        q.addBindValue(rating);
        q.exec();
    }
    
    QVariant addGenre(QSqlQuery &q, const QString &name)
    {
        q.addBindValue(name);
        q.exec();
        return q.lastInsertId();
    }
    
    QVariant addAuthor(QSqlQuery &q, const QString &name, const QDate &birthdate)
    {
        q.addBindValue(name);
        q.addBindValue(birthdate);
        q.exec();
        return q.lastInsertId();
    }
    
    QSqlError initDb()
    {
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
        db.setDatabaseName(":memory:");
    
        if (!db.open())
            return db.lastError();
    
        QStringList tables = db.tables();
        if (tables.contains("books", Qt::CaseInsensitive)
            && tables.contains("authors", Qt::CaseInsensitive))
            return QSqlError();
    
        QSqlQuery q;
        if (!q.exec(QLatin1String("create table books(id integer primary key, title varchar, author integer, genre integer, year integer, rating integer)")))
            return q.lastError();
        if (!q.exec(QLatin1String("create table authors(id integer primary key, name varchar, birthdate date)")))
            return q.lastError();
        if (!q.exec(QLatin1String("create table genres(id integer primary key, name varchar)")))
            return q.lastError();
    
        if (!q.prepare(QLatin1String("insert into authors(name, birthdate) values(?, ?)")))
            return q.lastError();
        QVariant asimovId = addAuthor(q, QLatin1String("Isaac Asimov"), QDate(1920, 2, 1));
        QVariant greeneId = addAuthor(q, QLatin1String("Graham Greene"), QDate(1904, 10, 2));
        QVariant pratchettId = addAuthor(q, QLatin1String("Terry Pratchett"), QDate(1948, 4, 28));
    
        if (!q.prepare(QLatin1String("insert into genres(name) values(?)")))
            return q.lastError();
        QVariant sfiction = addGenre(q, QLatin1String("Science Fiction"));
        QVariant fiction = addGenre(q, QLatin1String("Fiction"));
        QVariant fantasy = addGenre(q, QLatin1String("Fantasy"));
    
        if (!q.prepare(QLatin1String("insert into books(title, year, author, genre, rating) values(?, ?, ?, ?, ?)")))
            return q.lastError();
        addBook(q, QLatin1String("Foundation"), 1951, asimovId, sfiction, 3);
        addBook(q, QLatin1String("Foundation and Empire"), 1952, asimovId, sfiction, 4);
        addBook(q, QLatin1String("Second Foundation"), 1953, asimovId, sfiction, 3);
        addBook(q, QLatin1String("Foundation's Edge"), 1982, asimovId, sfiction, 3);
        addBook(q, QLatin1String("Foundation and Earth"), 1986, asimovId, sfiction, 4);
        addBook(q, QLatin1String("Prelude to Foundation"), 1988, asimovId, sfiction, 3);
        addBook(q, QLatin1String("Forward the Foundation"), 1993, asimovId, sfiction, 3);
        addBook(q, QLatin1String("The Power and the Glory"), 1940, greeneId, fiction, 4);
        addBook(q, QLatin1String("The Third Man"), 1950, greeneId, fiction, 5);
        addBook(q, QLatin1String("Our Man in Havana"), 1958, greeneId, fiction, 4);
        addBook(q, QLatin1String("Guards! Guards!"), 1989, pratchettId, fantasy, 3);
        addBook(q, QLatin1String("Night Watch"), 2002, pratchettId, fantasy, 3);
        addBook(q, QLatin1String("Going Postal"), 2004, pratchettId, fantasy, 3);
    
        return QSqlError();
    }
    
    #endif
    

    初始化数据库的流程是:1、重载addDatabase驱动为sqlite3;2、设置数据库名,这里“:memory:”代表存放在内存中,即程序完成后就释放掉了,如果要使用文件存储,则为文件路径;3、打开数据库;4、创建表格;5、插入数据,插入数据时对应用和数据库操作又做了一层封装。

    最后是bookdelegate.cpp:

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the demonstration applications of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:LGPL21$
    ** Commercial License Usage
    ** Licensees holding valid commercial Qt licenses may use this file in
    ** accordance with the commercial license agreement provided with the
    ** Software or, alternatively, in accordance with the terms contained in
    ** a written agreement between you and The Qt Company. For licensing terms
    ** and conditions see http://www.qt.io/terms-conditions. For further
    ** information use the contact form at http://www.qt.io/contact-us.
    **
    ** GNU Lesser General Public License Usage
    ** Alternatively, this file may be used under the terms of the GNU Lesser
    ** General Public License version 2.1 or version 3 as published by the Free
    ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
    ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
    ** following information to ensure the GNU Lesser General Public License
    ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
    ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    **
    ** As a special exception, The Qt Company gives you certain additional
    ** rights. These rights are described in The Qt Company LGPL Exception
    ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/
    
    #include "bookdelegate.h"
    
    #include <QtWidgets>
    
    BookDelegate::BookDelegate(QObject *parent)
        : QSqlRelationalDelegate(parent), star(QPixmap(":images/star.png"))
    {
    }
    
    void BookDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                               const QModelIndex &index) const
    {
        if (index.column() != 5) {
            QStyleOptionViewItem opt = option;
            opt.rect.adjust(0, 0, -1, -1); // since we draw the grid ourselves
            QSqlRelationalDelegate::paint(painter, opt, index);
        } else {
            const QAbstractItemModel *model = index.model();
            QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled) ?
                (option.state & QStyle::State_Active) ? QPalette::Normal : QPalette::Inactive : QPalette::Disabled;
    
            if (option.state & QStyle::State_Selected)
                painter->fillRect(option.rect, option.palette.color(cg, QPalette::Highlight));
    
            int rating = model->data(index, Qt::DisplayRole).toInt();
            int width = star.width();
            int height = star.height();
            int x = option.rect.x();
            int y = option.rect.y() + (option.rect.height() / 2) - (height / 2);
            for (int i = 0; i < rating; ++i) {
                painter->drawPixmap(x, y, star);
                x += width;
            }
            drawFocus(painter, option, option.rect.adjusted(0, 0, -1, -1)); // since we draw the grid ourselves
        }
    
        QPen pen = painter->pen();
        painter->setPen(option.palette.color(QPalette::Mid));
        painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
        painter->drawLine(option.rect.topRight(), option.rect.bottomRight());
        painter->setPen(pen);
    }
    
    QSize BookDelegate::sizeHint(const QStyleOptionViewItem &option,
                                     const QModelIndex &index) const
    {
        if (index.column() == 5)
            return QSize(5 * star.width(), star.height()) + QSize(1, 1);
    
        return QSqlRelationalDelegate::sizeHint(option, index) + QSize(1, 1); // since we draw the grid ourselves
    }
    
    bool BookDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
                                   const QStyleOptionViewItem &option,
                                   const QModelIndex &index)
    {
        if (index.column() != 5)
            return QSqlRelationalDelegate::editorEvent(event, model, option, index);
    
        if (event->type() == QEvent::MouseButtonPress) {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
            int stars = qBound(0, int(0.7 + qreal(mouseEvent->pos().x()
                - option.rect.x()) / star.width()), 5);
            model->setData(index, QVariant(stars));
            return false; //so that the selection can change
        }
    
        return true;
    }
    
    QWidget *BookDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                                        const QModelIndex &index) const
    {
        if (index.column() != 4)
            return QSqlRelationalDelegate::createEditor(parent, option, index);
    
        // for editing the year, return a spinbox with a range from -1000 to 2100.
        QSpinBox *sb = new QSpinBox(parent);
        sb->setFrame(false);
        sb->setMaximum(2100);
        sb->setMinimum(-1000);
    
        return sb;
    }
    

    可以看出其继承自QSqlRelationalDelegate,对于QSqlRelationalDelegate类根据帮助信息可以看出其是对QSqlRelationalTableModel中的数据进行显示和修改的一个类,所以该类的操作其实是对我们选择的数据模型的scoretable的重写操作。

    四、最后

    每个示例都代表了一个应用方向,时间允许的话可以都阅读分析一下,但是要掌握的核心内容就是如何使用数据库,然后显示数据库数据,搞清楚其流程然后自己写个例子熟悉一下,Qt的数据库编程基本上就没有什么大问题了。

    其实整个的分析过程中我们可以将其看作一个拼图游戏,我们知道最终的效果,就像我们知道最终会是什么样子,然后我们去完成拼图,虽然单独某个图块不熟悉,但是只要方向不错,那么最终仍然会拼出结果。这些小的图块就类似于代码中的事件用法、c++语法、控件用法等,我们可能在初期对其不甚了解,但只要方向没错,最终总会得到想要的结果,只是时间长短而已,并且随着了解的深入,对每一个图块也会越来越熟悉。

    展开全文
  • VB获得Access数据库信息,定义好数据库连接字串后,正常连接数据库文件,然后获取数据的记录数目、最后修改时间、创建时间、列出数据表名称等信息,一个简单的Access数据库操作例子。
  • 声明:这是数据库编程,不要和我讲效率低什么的 单表查询select语句的执行原理: 1、先将你sql中写的字段、连表给预先 理解(如 下面的例子各种连表) 2、在执行where后面的;如果有子查询,先执行括号里的 如 ...

    声明:这是数据库编程,不要和我讲效率低什么的

    表查询select语句的执行原理:
    1、先将你sql中写的字段、连表给预先 理解(如  下面的例子各种连表)
    2、在执行where后面的;如果有子查询,先执行括号里的 如 select * from a where id in (select pid from b where = 66) //查出b表的id,和a表中的id做匹配,只取a表匹配到的
    3、最后输出字段(这时已经计算好了)

    表查询select语句的执行原理:

    1、先执行on 后执行where

    ON 条件(“A LEFT JOIN B ON 条件表达式”中的ON)用来决定如何从 B 表中检索数据行。如果 B 表中没有任何一行数据匹配 ON 的条件,将会额外生成一行所有列为 NULL 的数据,在匹配阶段 WHERE 子句的条件都不会被使用。仅在匹配阶段完成以后,WHERE 子句条件才会被使用。它将从匹配阶段产生的数据中检索过滤。

     

    总结:
    派生表的作用很多:可以计算、可以做同时输出
    字段中也可以写sql,用小括号括起来即可,sql先计算()内的,将结果给字段做运算

     

    例子1、同一个字段,俩种状态,要同时在同一行输出,不能用or怎么搞

    效果图:

    sql:

    例子2、一个字段,2个标识位,代表3种状态;这里查的是纯优惠的

    该字段逻辑有点特殊,特附图:

    -- 142行的having要放在最下面,原因1:having是对查出来的结果在筛选,而where是查之前进行筛选;
    -- 原因2:having支持通过字段别名(mini_contract就是别名),进行筛选,where只支持原来的字段名

    例子3、直接在字段上做计算:减法(书:mysql必知必会,10.3执行算数计算)

    例子4、函数写在判断外面

    例子5、算四季,春夏秋冬

    
    if(
    	DATE_FORMAT(d3.create_time, '%m') = 04,	-- 第1个参数
    	case
    	when
    		FIND_IN_SET(DATE_FORMAT(d3.create_time, '%m'),'03,04,05') <> 0 -- 不等于0是,月份在'3,4,5'中
    	then '春' 
    	when
    		FIND_IN_SET(DATE_FORMAT(d3.create_time, '%m'),'06,07,08') <> 0
    	then '夏' 
    	when
    		FIND_IN_SET(DATE_FORMAT(d3.create_time, '%m'),'09,10,11') <> 0
    	then '秋' 
    	when
    		FIND_IN_SET(DATE_FORMAT(d3.create_time, '%m'),'12,01,02') <> 0
    	then '冬' 
    	end,
    	d3.create_time	-- 第3个参数
    )
    as 回访季度  

    例子6、定义变量

    -- 自定义变量,计算行号
    SELECT
    @row := @row + 1 as 行号,  -- 迭代器+1
    fenxiao.*
    FROM fenxiao, (SELECT @row := 0) t -- 虚个表,将变量置位0
    WHERE @row < 8 -- 输出行号<8的数据

    例子7:where上做计算,及其优化

    需求:统计 实付 > 原价70% 的人数

    例子8:on是个连表条件,不止能用=

    =是个表达式,大于 小于 也是个表达式,既然 这样,那子查询 也没问题咯

    例子9:on后面多个条件,用()

    例子10:在case中 没有 select ... from ... where 的可以直接使用and

    想明白了,不奇葩,就是一个or的关系,如第6行  4个条件,其中一个为真 就输出 班主任

    如果case中表达式:相当于 输出结果后,在where一遍(case中的like 大于 小于啊)

    如果case中没有表达式:相当于是个if else的功能

    例子11:函数里面写关键词

    例子11:在字段上进行子查询

    注意:这里用了完全限定表名,子查询中的where其实是个连表

    例子12:连表中,同时满足多个条件

        //对应的伪代码,就是这个意思
        if(年级 && 班型 && 产品体系){
          echo slpp.per_price as 课酬;
        }else{
          echo "";
        }

    例子13:某一个日期 在 某个时间段之内

    select 
    	bodla.bodla_create_time,
    	bdslm.bdslm_begin_date as 校区法人有效期_开始时间,
    	bdslm.bdslm_end_date as 校区法人有效期_结束时间
    from boss_ods_delay_learning_application as bodla
    left join boss_dw_school_legal_manage as bdslm on bodla.bodla_blcampus_id=bdslm.bdslm_orgID
    -- 查 DATE(bodla.bodla_create_time) 在 开始时间和结束时间之间的
    where DATE(bodla.bodla_create_time) BETWEEN bdslm.bdslm_begin_date AND bdslm.bdslm_end_date
    limit 10 

    例子14:每月的金额 汇总

     

     

    展开全文
  • Java-数据库编程技术(MySQL)

    千次阅读 2018-04-20 19:46:34
    数据库简介 什么是数据库 数据库(Database,DB)就是存放数据的仓库,为了实现一定目的,按照某种规则组织起来的数据的集合。当然数据有多种形式,如文字、数码、符号、图形、声音等。从广义的角度上定义,计算机...

    初识MySQL

    数据库简介

    什么是数据库

    数据库(Database,DB)就是存放数据的仓库,为了实现一定目的,按照某种规则组织起来的数据的集合。当然数据有多种形式,如文字、数码、符号、图形、声音等。从广义的角度上定义,计算机中任何可以保存数据的文件或者系统我们都可以称之为数据库,如一个Word文件等。

    常见数据库

    1. Oracle
    2. SQL Server
    3. MySQL

    我们详细了解一下MySQL相对于其他数据库的优势:

    • 运行速度快:MySQL体积小,命令执行的速度快
    • 使用成本低:MySQL是开源的,且提供免费版本,对大多数用户来说大大降低了使用成本
    • 容易使用:与其他大型数据库的设置和管理相比,其复杂程度较低,易于使用
    • 可移植性强:MySQL能够运行于多种系统平台上,如Windows、Linux、UNIX等
    • 使用更多用户:MySQL支持最常用的数据管理功能,适用于中小企业甚至大型网站应用

    实体和数据库表

    这里写图片描述
    上图为数据库中存储的数据表格

    每一行(Row)实际上对应一个实体,在数据库中通常叫做一条"记录"

    每一列,如"id",“name"等,在数据库中通常称之为"字段”

    上图中将相同类型的记录组织在一起的数据结构称为数据库"表"(Table),表是实体的集合

    主键和外键

    主键

    主键:一列的值用来唯一标识表中的每一行,用于强制表的实体完整性

    注意:
    一个表只能有一个主键,并且主键列不允许出现空值(NULL),尽管有的表中允许没有主键,但是通常情况下建议为表设置主键。

    复合主键:如果两列或多列组合起来唯一的标识表中的每一行,则该主键也叫做复合主键。

    选择主键的原则:

    1. 最少性
    2. 稳定性

    外键

    外键:如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键。由此可见,外键表示了两个关系之间的相关联系。以另一个关系的外键作主关键字的表被称为主表,具有此外键的表被称为主表的从表。外键又称作外关键字。

    命令行连接MySQL

    命令行方式连接数据库

    语法:

    #host--->服务器主机地址
    #username--->数据库用户名
    #password--->数据库密码
    
    mysql -h host -u username -p password
    

    注意:
    如果是在本机操作,可省略-h参数
    -p后面可以不写密码,按Enter后输入密码。如果写密码,-p和密码间没有空格。

    例如
    这里写图片描述 或者
    这里写图片描述

    登录之后,可以用以下指令查看当前的MySQL版本信息以及用户名:

    SELECT VERSION(),USER();
    

    例如:
    这里写图片描述

    SQL简介

    什么是SQL

    SQL全称是:结构化查询语言(Structured Query Language),是关系数据库的标准语言

    SQL的组成

    1. DML(Data Manipulation Language,数据操作语言,也称为数据操纵语言):用来插入、修改和删除数据库中的数据,如INSERT UPDATE DELETE
    2. DDL(Data Definition Language,数据定义语言):用来建立数据库、数据库对象和定义其列,大部分是以CREATE开头的命令,如CREATE TABLE``CREATE VIEW以及DROP TABLE
    3. DQL(Data Query Language,数据库查询语言):用来对数据库中的数据进行查询,如SELECT
    4. DCL(Data Control Language,数据控制语言):用来控制数据库组件的存取许可、存取权限等,如GRANTREVOKE

    SQL中的运算符

    1. 算术运算符:+ - * / %这五个与Java是同样的意思和用法
    2. 赋值运算符:=同样与Java意思用法相同
    3. 比较运算符:> < >= <= !=(不等于,非SQL-92标准)与Java用法相同,除此之外=表示等于,<>表示不等于
    4. 逻辑运算符:AND OR NOT:分别相当于Java的&& || !

    例如:

    NOT(性别 = '男') AND (年龄>=18 AND 年龄<=45)
    

    使用DDL语句操作数据库

    创建数据库

    语法:

    CREATE DATABASE 数据库名;
    

    例如:
    创建dog数据库的语句如下

    CREATE DATABASE dog;
    

    结果如下:
    这里写图片描述

    注意:
    在MySQL中,以英文半角分号;作为一条命令的结束符,且在Windows系统下,默认不区分大小写。

    查看数据库列表

    语法:

    SHOW DATABASES;
    

    运行结果如下
    这里写图片描述

    选择数据库

    语法:

    USER 数据库名;
    

    例如:

    USE tangccoep;
    USE test;
    

    运行结果如下:
    这里写图片描述

    删除数据库

    语法:

    DROP DATABASE 数据库名;
    

    例如:

    DROP DATABASE dog;
    

    运行结果如下:
    这里写图片描述

    使用DDL语句操作数据表

    数据类型

    数值类型

    数值数据类型:存储数值,每种类型具有不同的存储范围,支持取值范围越大,所需存储空间越多。所有数值类型(除BITBoolean外)都可以有符号或无符号,有符号数据列可存储正或负的数值,默认情况为有符号。具体类型描述如下表:

    数据类型字节说明
    TINYINT[(M)]1字节有符号值:-27~27;无符号值:0~2^8-1
    SMALLINT[(M)]2字节有符号值:-32768 到32767(- 2^15 到2^15-1;无符号值:0到65535(0 到2^16 -1)
    MEDIUMINT[(M)]3字节有符号值:-8388608 到8388607(- 2^23 到2^23 -1);无符号值:0到16777215(0 到2^24 -1)
    INT[(M)]4字节有符号值:-2147683648 到2147683647(- 2^31 到2^31 -1)无符号值:0到4294967295(0 到2^32 -1)
    FLOAT[(M,D)]4字节有符号值:-3.402823466E+38-1.175494351E-38;无符号值:1.175494351E-383.402823466E+38
    DOUBLE[(M,D)]8字节有符号值:-1.7976931348623157E+308 ~ -2.2250738585072014E-308;无符号值:2.2250738585072014E-308 ~ 1.7976931348623157E+308
    DECIMAL[(M[,D])]M+2字节M:最大精度位数即总位数,取值范围1 ~ 65,默认值为10;D:小数位精度位数,D的取值范围是0 ~ 30;该类型可能的取值范围与DOUBLE相同,但有效取值范围由M、D决定,例如类型为DECIMAL(5,2)的字段取值范围是-999.99 ~ 999.99

    MySQL提供了5种整型: tinyintsmallintmediumintintbigint(字节数1、2、3、4、8),这些类型在可表示的取值范围上是不同的。整数列可定义为unsigned从而禁用负值;这使列的取值范围为0以上。

    MySQL 提供三种浮点类型: floatdoubledecimal。与整型不同,浮点类型不能是unsigned的,其取值范围也与整型不同,这种不同不仅在于这些类型有最大值,而且还有最小非零值。最小值提供了相应类型精度的一种度量,这对于记录科学数据来说是非常重要的(当然,也有负的最大和最小值)。

    在选择了某种数值类型时,应该考虑所要表示的值的范围,只需选择能覆盖要取值的范围的最小类型即可。选择较大类型会对空间造成浪费,使表不必要地增大,处理起来没有选择较小类型那样有效。对于整型值,如果数据取值范围较小,如人员年龄或兄弟姐妹数,则tinyint最合适。mediumint能够表示数百万的值并且可用于更多类型的值,但存储代价较大。bigint在全部整型中取值范围最大,而且需要的存储空间是表示范围次大的整型int类型的两倍,因此只在确实需要时才用。对于浮点值,double占用float的两倍空间。除非特别需要高精度或范围极大的值,一般应使用只用一半存储代价的float型来表示数据。

    在定义整型列时,可以指定可选的显示尺寸m。如果这样,m应该是一个1 到255的整数。它表示用来显示列中值的字符数。例如,mediumint(4)指定了一个具有4个字符显示宽度的mediumint列。如果定义了一个没有明确宽度的整数列,将会自动分配给它一个缺省的宽度。缺省值为每种类型的"最长"值的长度。如果某个特定值的可打印表示需要不止m个字符,则显示完全的值;不会将值截断以适合m个字符。需要注意的是,使用一个宽度指示器不会影响字段的大小和它可以存储的值的范围。

    对每种浮点类型,可指定一个最大的显示尺寸m 和小数位数dm 的值应该取1 到255。d的值可为0 到3 0,但是不应大于m – 2(如果熟悉odbc 术语,就会知道md 对应于odbc 概念的"精度"和"小数点位数")。mdfloatdouble 都是可选的,但对于decimal是必须的。在选项md时,如果省略了它们,则使用缺省值。

    串类型(包括字符串)

    串数据类型:最常用的数据类型,有两种基本的串类型:分别为定长串和不定长串。定长串结束长度固定的字符,其长度是创建表是指定的,不允许多于指定的字符数据,它们分配的存储空间与指定的一样多,CHAR属于定长串类型。变长串存储长度可变的文本,有些变长数据类型具有最大的定长,而有些则是完全变长的,不管哪种只有指定的数据得到保存(不会添加额外的空格保存),TEXT属于变长串类型。变长数据类型灵活,定长数据类型高效,MySQL处理定长数据类型比变长列快很多,MySQL不允许对变长列(或一个列的可变部分)进行索引,这会极大影响性能。具体类型描述如下表:

    数据类型字节说明
    CHAR[(M)]M字节固定长字符串;M为0 ~ 225的整数;它的长度必须在创建时指定,否则MySQL假定为CHAR(1)
    VARCHAR[(M)]可变长度可变长度;M为0 ~ 65535的整数
    TINYTEXT0 ~ 255微型字符串
    MEDIUMTEXT0 ~ 16383中型文本串
    TEXT0 ~ 65535文本串
    LONGTEXT最大长度4GB纯文本串,一般不会到4GB
    ENUM-接受最多64K个串组成的预定义集合的某个串
    SET-接受最多64K个串组成的预定义集合的零个或多个串

    注意:
    不管任何形式的串数据类型,串值都必须在引号内(通常单引号更好);如果数值是计算中使用的数值,则应存储在数值数据类型列中,如果作为字符串使用(如电话号码、邮政编码)则应保存在串数据类型列中。

    日期和时间数据类型

    MySQl中有多种表示日期和时间的数据类型。其中YEAR表示年份,DATE表示日期,TIME表示时间,DATETIMETIMESTAMP表示日期和实践。具体如下表:

    数据类型存储字节数格式取值范围
    DATE4YYYY-MM-DD1000-01-01 ~ 9999-12-31
    TIME3YY-MM-DD hh:mm:ss:-838:59:59 ~ 838:59:59
    DATETIME8hh:mm:ss:1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
    TIMESTAMP4YYYYMMDDHHMMSS19700101080001 ~ 20380119111407
    YEAR1YYYY格式的年份1901 ~ 2155

    当插入值超出有效取值范围时,系统会报错,并将零值插入到数据库中。

    MySQL是以 YYYY-MM-DD 格式来显示DATE类型的值,插入数据时,数据可以保持这种格式。另外,MySQL还支持一些不严格的语法格式,分隔符"-"可以用"@""."等符号来替代。 在插入数据时,也可以使用"YY-MM-DD"格式,YY转化成对应的年份的规则与YEAR类型类似。如果我们想插入当前系统的时间,则可以插入CURRENT_DATE或者NOW()

    TIME类型表示为"时:分:秒",尽管小时范围一般是0~23,但是为了表示某些特殊时间间隔,MySQL将TIME的小时范围扩发了,而且支持负值。对TIME类型赋值,标准格式是'HH:MM:SS',但不一定非要是这种格式。 如果插入的是'D HH:MM:SS'格式,则类似插入了'(D*24+HH):MM:SS'。比如插入'2 23:50:50',相当于插入了'71:50:50'。如果插入的是'HH:MM''SS'格式,则效果是其他未被表示位的值赋为零值。比如插入'30',相当于插入了'00:00:30';如果插入'11:25',相当于插入了'11:25:00'。在MySQl中,对于'HHMMSS'格式,系统能够自动转化为标准格式。如果我们想插入当前系统的时间,则可以插入CURRENT_TIME或者NOW()

    DATETIME类型准格式为"YYYY-MM-DD HH:MM:SS",具体赋值方法与上面的方法相似。

    TIMESTAMP的取值范围比较小,没有DATETIME的取值范围大,因此输入值时一定要保证在TIMESTAMP的范围之内。它的插入也与插入其他日期和时间数据类型类似。那么TIMESTAMP类型如何插入当前时间?第一,可以使用CURRENT_TIMESTAMP;第二,输入NULL,系统自动输入当前的TIMESTAMP;第三,无任何输入,系统自动输入当前的TIMESTAMP。 另外有很特殊的一点:TIMESTAMP的数值是与时区相关。

    YEAR类型赋值可以有三种方法: 第一种是直接插入4位字符串或者4位数字; 第二种是插入2位字符串,这种情况下如果插入'00'~'69',则相当于插入2000~2069;如果插入'70'~'99',则相当于插入1970~1999。第二种情况下插入的如果是'0',则与插入'00'效果相同,都是表示2000年; 第三种是插入2位数字,它与第二种(插入两位字符串)不同之处仅在于:如果插入的是一位数字0,则表示的是0000,而不是2000年。所以在给YEAR类型赋值时,一定要分清0'0',虽然两者相差个引号,但实际效果确实相差了2000年

    二进制数据类型

    二进制类型可存储任何数据,如文字、图像、多媒体等。具体类型描述如下:

    数据类型说明
    TITYBLOB最大长度为255字节
    BLOB最大长度为64KB
    MEDIUMBLOB最大长度为16MB
    LONGBLOB最大长度为4GB

    创建表

    语法:

    CREATE TABLE [IF NOT EXISTS] 表名(
    	字段1 数据类型 [字段属性][约束][索引][注释],
    	字段2 数据类型 [字段属性][约束][索引][注释],
    	......
    	字段n 数据类型 [字段属性][约束][索引][注释],
    )[表类型][表字符集][注释];
    

    字段约束与属性

    常用的属性约束如下表:

    字段属性、约束名关键字说明
    非空约束NOT NULL如该字段不允许为空,需要设置NOT NULL约束,如学生姓名字段不允许为空
    默认约束DEFAULT赋予某字段默认值,如果该字段没有插入数据,则其值为默认值,如学生表中男生居多,可设置性别列默认值为"男"
    唯一约束UNIQUE KEY(UK)设置字段的只是唯一的。允许为空,但只能有一个空值
    主键约束PRIMARY KEY(PK)设置该字段为表的主键,可以作为该表记录的唯一标识,如学生号能唯一确定一名学生,可设置为主键
    外键约束FOREIGN KEY(FK)用于在两表之间建立关系,需要指定引用主表的哪一字段。在发生插入或更新表中数据时,数据库将自动检查更新的字段值是否符合约束的限制。如果不符合约束要求,则更新操作失败。使用时注意:(1)InnoDB支持外键,MyISAM不支持,外键关联的表要求都是InnoDB类型的表;(2)作为外键的字段要求在主表中是主键(单字段主键)
    自动增长AUTO_INCREMENT(1)设置该列为自增字段,默认每条自增1;
    (2)通常用于设置主键,且为整数类型;
    (3)可设置初始值和步长

    主键可以是单字段的,也可以是多字段的

    1.单字段主键

    在定义字段的同时定义主键,语法如下:

    CREATE TABLE [IF NOT EXISTS] 表名(
    	字段1 数据类型 PRIMARY KEY;
    	......
    );
    

    在定义完所有字段之后定义主键,语法如下:

    CREATE TABLE [IF NOT EXISTS] 表名(
    	字段1 数据类型,
    	......
    	[CONSTRAINT<约束名>] PRIMARY KEY[列名]
    );
    

    例如:

    CREATE TABLE student(
    	`studentNo` INT(4) PRIMARY KEY;
    	......
    );
    

    或者:

    CREATE TABLE student(
    	`studentNo` INT(4),
    	......
    	PRIMARY KEY(`id`)
    );
    
    2.多字段联合主键

    主键由多字段组成,语法如下:

    CREATE TABLE [IF NOT EXISTS] 表名(
    	......
    	PRIMARY KEY [字段1,字段2......]
    );
    

    例如:

    CREATE TABLE tb_temp(
    	`id` INT(4),
    	`name` VARCHAR(11),
    	......
    	PRIMARY KEY(`id`,`name`)
    );
    

    注释

    在创建表的同时可以为表或字段添加说明性的文字,即注释。
    注释是使用COMMENT关键字来添加的。

    例如:

    CREATE TABLE test(
    	`id` INT(11) UNSIGNED COMMENT `编号`
    )COMMENT='测试表';
    

    编码格式设置

    可以在创建表时指定字符集,语法如下:

    CREAT TABLE [IF NOT EXISTS] 表名(
    	#省略代码
    )CHARSET = 字符集名;
    

    下面利用CREATE TABLE语句在数据库myschool中创建学生表student,具体设计如下表所示:

    序号字段名称字段说明数据类型长度属性备注
    1studentNo学号INT4非空,主键
    2loginPwd密码VARCHAR20非空
    3studentName姓名VARCHAR50非空
    4sex性别CHAR2非空,默认值"男"
    5gradeId年级编号INT4无符号
    6phone联系电话VARCHAR50
    7address地址VARCHAR255默认值"地址不详"
    8bornDate出生日期DATETIME
    9email邮件账号VARCHAR50
    10identityCard身份证号VARCHAR18唯一身份证号全国唯一

    详细代码如下:

    CREATE TABLE `student`(
    	`studentNo` INT(4) NOT NULL COMMENT '学号' PRIMARY KEY, #非空主键
    	`loginPwd` VARCHAR(20) NOT NULL COMMENT '密码',
    	`studentName` VARCHAR(50) NOT NULL COMMENT '学生姓名',
    	`sex` CHAR(2) DEFAULT '男' NOT NULL COMMENT '性别', #非空,默认值男
    	`gradeId` INT(4) UNSIGNED COMMENT '年级编号', #无符号数
    	`phone` VARCHAR(50) COMMENT '联系电话',
    	`address` VARCHAR(255) DEFAULT '地址不详' COMMENT '地址',  #默认值"地址不详"
    	`bornDate` DATETIME COMMENT '出生日期',
    	`email` VARCHAR(50) COMMENT '邮件账号',
    	`identityCard` VARCHAR(18) UNIQUE KEY COMMENT '身份证号'  #唯一
    )COMMENT='';  #表注释"学生表"
    

    查看表

    显示数据库中的所有表名称,语法如下:

    SHOW TABLES;
    

    查看表的定义,语法如下:

    DESCRIBE 表名;DESC 表名;
    

    例如,查看myschool数据库中的student表,SQL语句如下:

    USER myschool;
    DESCRIBE `student`;
    

    删除表

    语法:

    DROP TABLE [IF EXISTS] 表名;
    

    例如:

    DROP TABLE `student`;
    

    创建student表的语句改写成完整的创建表的语句,如下所示:

    USE myschool;
    DROP TABLE IF EXISTS `student`;
    CREATE TABLE 'student'(
    	......
    );
    

    修改表

    修改表名

    语法如下:

    ALTER TABLE<旧表名> RENAME [TO] <新表名>;
    #TO 为可选参数,使用与否不影响结果。仅修改表名,表结构不变
    

    例如:
    实现在test数据库中创建表demo01,将其改名为demo02,SQL语句如下:

    DROP TABLE IF EXISTS `demo01`;
    CREATE TABLE IF NOT EXISTS `demo01`(
    	`id` INT(10) NOT NULL AUTO_INCREMENT,
    	`name` VARCHAR(8) NOT NULL,
    	PRIMARY KEY(`id`)
    );
    #修改表名
    ALTER TABLE `demo01` RENAME `demo02`;
    

    添加字段

    添加字段的语法如下:

    ALTER TABLE 表名 ADD 字段名 数据类型 [属性];
    

    例如,向demo02表中添加密码字段,SQL语句如下:

    #添加字段
    ALTER TABLE demo02 ADD `password` VARCHAR(20) NOT NULL;
    

    修改字段

    修改字段,可以包括修改字段名和修改数据存储的类型。SQL语句如下:

    ALTER TABLE 表名 CHANGE 原字段名 新字段名 数据类型 [属性];
    

    其中,"原字段名"指修改前的字段名,"新字段名"指修改后的字段名,"数据类型"指修改后的数据类型,如果不需要修改数据类型,则和原数据类型保持一致,但"数据类型"不能为空

    例如:
    demo02表中name字段名改为username,数据类型改为CHAR(10),SQL语句如下:

    #修改字段名
    ALTER TABLE demo02 CHANGE `name` `username` CHAR(10) NOT NULL;
    

    删除字段

    将数据表中的某个字段从表中删除,语法如下:

    ALTER TABLE 表名 DROP 字段名;
    

    例如: 删除demo02表中password字段,SQL语句如下:

    #删除字段
    ALTER TABLE demo02 DROP `password`;
    

    MySQL系统帮助

    暂无

    DML和DQL

    MySQL的存储引擎

    暂无

    使用DML插入数据

    INSERT插入数据

    1.插入单行数据

    语法:

    INSERT INTO 表名 [(字段名列表)] VALUES (值列表);
    

    其中:

    • 表的字段名是可选的,如果省略,则依次插入所有字段
    • 多个列表和多个值之间使用逗号分隔
    • 值列表必须和字段名列表数量相同,且数据类型相符
    • 如果插入的是表中部分数据,字段名列表必须填写
    • 如果插入数据的值列表与表的字段名列表一一对应且个数相同,则字段名可以省略

    例如,向student表中插入一条记录:

    INSERT INTO `student` 
    (`loginPwd`,`studentName`,`gradeId`
    ,`phone`,`bornDate`) 
    VALUES('123','黄小平',1,'13988888888','1996-5-8');
    #或者 插入数据的值列表与表的字段名列表一一对应且个数相同
    #,则字段名可以省略
    INSERT INTO `student`
    VALUES('123','黄小平',1,'13988888888','1996-5-8');
    

    2.插入多行数据

    语法:

    INSERT INTO 表名(字段名列表) VALUES(值列表1),(值列表2),...,(值列表n);
    

    例如,一次向subject表中插入三条数据,SQL语句如下:

    INSERT INTO `subject`(`subjectName`,`classHour`,`gradeID`) 
    VALUES('Logic Java',220,1),('HTML',160,1),('Java OOP',230,2);
    

    3.将查询结果插入到新表

    语法:

    CREATE TABLE 新表(SELECT 字段1,字段2,...... FROM 原表);
    

    例如,将student表中的studentNamephone字段数据保存到新表phoneList中,SQL语句如下:

    CREATE TABLE `phoneList` (SELECT `studentName`,`phone` FROM `student`);
    

    使用DML更新数据

    语法:

    UPDATE 表名 SET 列名1=更新值1,列名2=更新值2 [WHERE 更新条件];
    

    其中:
    (1)SET后面可以紧随多个"列名=更新值",修改多个数据列的值,不限一个,使用逗号分隔。
    (2)WHERE子句是可选的,用来限制更新数据的条件,若不限制,则整个表的所有数据行都会被更新。

    例如:

    #student表中,要把所有学生性别更新为女性
    UPDATE `student` SET sex='女';
    

    对于地址为'清华大学'的学生,若这个班级改为北京大学,则需要按照条件更新

    UPDATE student
    SET address='北京大学'
    WHERE address='清华大学';
    

    将所有分数低于或等于95分的成绩都在原来的基础上加5分,代码如下:

    UPDATE result
    SET studentResult = studentResult + 5
    WHERE studentResult<=95;
    

    注意: 更新数据时,一般都有条件限制,别忘了写WHERE条件语句,否则将更新表中的所有行的数据,这可能导致有效数据的丢失。

    使用DML删除数据

    DELETE删除数据

    语法如下:

    DELETE [FROM] 表名 [WHERE<删除条件>];
    

    例如:

    #删除学生表中姓名为'小明'的数据的SQL语句如下:
    DELETE FROM `student` WHERE studentName = '小明';
    

    注意:

    #如果要删除的行的主键值被其他表引用,
    #例如分数表中的studentID引用了学生表中的studentNo列,
    #也就是约束冲突!那么删除操作会报错,比如:
    DELETE FROM student WHERE studentNo = 22;
    

    TRUNCATE TABLE删除数据

    TRUNCATE TABLE用来删除表中的所有行,功能上类似于没有WHERE子句的DELETE语句。

    例如,要删除学生表中的所有记录行,代码如下:

    TRUNCATE TABLE student;
    

    DELETE相比较:
    优点:TRUNCATE TABLEDELETE执行速度快,使用的系统资源和事务日志资源更少,并且删除数据后表的标识列会重新开始编号。

    缺点:TRUNCATE TABLE删除表中的所有行,但是表的结构、列、约束、索引等不会被改动;TRUNCATE TABLE不能用于有外键约束引用的表,这种情况下,需要用DELETE语句;

    实际工作中,不建议使用TRUNCATE TABLE语句,因为使用它删除的数据不能恢复还原。

    DQL语句

    SELECT语句进行查询

    最简单的SELECT查询语句可以表示成如下语句:

    SELECT <列名|表达式|函数|常量>
    FROM <表名>
    [WHERE <查询条件表达式>]
    [ORDER BY <排序的列名> [ASCDESC]];
    #ASC升序 DESC降序 不写的话默认ASC
    

    1.查询所有的数据行和列

    例子:查学生表所有数据

    SELECT * FROM `student`
    

    2.查询部分行或列

    查询部分列需要列举不同的列名
    查询部分行需要使用WHERE子句进行条件限制
    例子:

    #查地址为北京的学生的编号和姓名
    SELECT `studentNo`,`studentName` FROM `student` 
    WHERE address = '北京';
    
    #查地址不在北京的学生编号和姓名
    SELECT `studentNo`,`studentName` FROM `student` 
    WHERE address <> '北京';
    

    3.在查询中使用列的别名

    1.AS子句可以用来改变结果集中列的名称,也可以为组合或者计算出的列指定名称,还有一种情况是让标题列的信息更易懂,例如,把studentNo列名查询后显示为"学生编号"。例如:

    SELECT `studentNo` AS 学生编号,`studentName` AS 学生姓名
    ,`address` AS 学生地址
    FROM `student`
    WHERE address <> '北京';
    

    2.使用计算、合并得到新列的命名。例如,假设在某数据库的顾源表employee中存在firstName列和lastName列,现在需要将这两列合并成一个叫做"姓名"的列,SQL语句如下:

    #SELECT `firstName` + '.' + `lastName` AS 姓名 FROM `employee`;
    #上面这句话是错的,不知道为什么,字符串拼接失败,输出0
    #应该使用CONCAT(str1,str2...,strn) 方法
    SELECT CONCAT(`firstName`, `lastName`) AS 姓名 FROM `employee`;
    

    4.查询空值

    在SQL语句中采用"IS NULL"或者"IS NOT NULL"来判断是否为空,因此,如果要查询学生表中没有填写email信息的学生,SQL语句如下:

    SELECT `studentName` FROM `student` WHERE `email` IS NULL;
    

    5.在查询中使用常量列

    将一些常量的默认信息添加到查询输出中,方便计算或统计。

    例如,查询学生信息的时候,学校名称统一都是"北大",SQL语句如下:

    SELECT `studentName` AS 姓名,`address` AS 地址,'北大' AS 学校名称
    FROM `student`;
    

    查询输出多了一列"学校名称",该列的所有数据都是"北大"

    常用函数

    1.聚合函数

    函数名作用
    AVG()返回某字段的平均值
    COUNT()返回某字段的行数
    MAX()返回某字段的最大值
    MIN()返回某字段的最小值
    SUM()返回某字段的和

    例如:

    #返回`student`表`score`列的总和
    SELECT SUM(score) FROM student;
    
    #返回`student`表`score`列的平均值
    SELECT AVG(score) FROM student;
    

    2.字符串函数

    函数名作用举例
    CONCAT(str1,str2,...,strn)连接字符串str1、str2、...、strn为一个完整字符串SELECT CONCAT('My','S','QL');
    返回:MySQL
    INSERT(str,pos,len,newstr)将字符串strpos位置开始,len个字符长的子串替换为字符串newstrSELECT INSERT('这是Oracle数据库',3,6,'MySQL');
    返回:这是MySQL数据库
    LOWER(str)将字符串str中所有字符变为小写SELECT LOWER('MySQL');
    返回:mysql
    UPPER(str)将字符串str中所有字符变为大写SELECT UPPER('MySQL');
    返回:MYSQL
    SUBSTRING(str,num,len)返回字符串str的第num个位置开始长度为len的子字符串SELECT SUBSTRING('JavaMySQLOracle',5,5);
    返回:MySQL

    例如:

    #将student表的studentName列改为大写:
    SELECT UPPER(`studentName`) FROM `student`;
    

    3.时间日期函数

    函数名作用举例(部分结果与当前日期有关)
    CURDATE()获取当前日期SELECT CURDATE();
    返回:2018-04-22(当前日期)
    CURTIME()获取当前时间SELECT CURTIME();
    返回:15:16:20(当前时间)
    NOW()获取当前日期和时间SELECT NOW();
    返回:2018-04-22 15:16:20(当前日期 当前时间)
    WEEK(date)返回日期date为一年中的第几周SELECT WEEK(NOW());
    返回:16(2018-04-22为2018年第16周)
    YEAR(date)返回日期date的年份SELECT YEAR(NOW());
    返回:2018(当前日期的年份)
    HOUR(time)返回时间time的小时值SELECT HOUR(NOW());
    返回:15
    MINUTE(time)返回时间time的分钟值SELECT MINUTE(NOW());
    返回:16
    DATEDIFF(date1,date2)返回日期参数date1date2之间相隔的天数SELECT DATEDIFF('2018-04-28','2018-04-25');
    返回:3
    SELECT DATEDIFF('2018-04-22','2018-04-25');
    返回:-3
    ADDDATE(date,n)计算日期参数date加上n天后的日期SELECT ADDDATE(NOW(),5);
    返回:2018-04-27 15:16:20(日期时间都显示)
    SELECT ADDDATE('2018-04-22',5);
    返回:2018-04-27(只显示日期)

    4.数学函数

    函数名作用举例
    CEIL(x)返回大于或等于数值x的最小整数SELECT CEIL(2.3);
    返回:3
    FLOOR(x)返回小于或等于数值x的最大整数SELECT FLOOR(2.3);
    返回:2
    RAND()返回0~1之间的随机数SELECT RAND();
    返回:0.552452347862356

    LIMIT子句

    语法:

    SELECT <字段名列表>
    FROM <表名或试图>
    [WHERE <查询条件>]
    [GROUP BY <分组的字段名>]
    [ORDER BY <排序的列名>[ASCDESC]]
    [LIMIT [位置偏移量, ]行数];
    
    #LIMIT介绍如下:
    #1.
    #位置偏移量指从结果集中第几条数据开始显示(第1条记录的位置偏移量是0,
    #第2条位置偏移量是1,..,第n条位置偏移量是n-1),
    #此参数可选,当省略时从第一条记录开始显示。
    #2.
    #行数指显示记录的条数
    

    LIMIT子句可以实现数据的分页查询,即从一批结果数据中,规定每页显示多少条数据,可以查询中间某页记录。LIMIT子句经常与ORDER BY子句一起使用,即先对查询结果进行排序,然后根据LIMIT的参数显示其中部分数据。

    例如:查询所有年级编号为1的学员信息,按学员升序显示前4条记录,SQL如下:

    SELECT * FROM `student` WHERE `gradeId` = 1
    ORDER BY `studentNo`
    LIMIT 4;
    

    以上例子省略位置偏移量,从第1条记录开始显示,如果每页显示4条记录,要求显示第2页全部数据,经过计算,应从第5条记录开始显示4条数据,SQL如下

    SELECT * FROM `student` WHERE `gradeId` = 1
    ORDER BY `studentNo`
    LIMIT 4,4;
    

    子查询

    子查询在WHERE子句中的一般用法如下:

    SELECT ...... FROM1 WHERE 字段1 比较运算符 (子查询);
    

    其中,子查询语句必须放在一对圆括号内;
    比较运算符包括>,=,<,>=,<=
    习惯上,外面的查询称为父查询,圆括号内嵌入的查询称为子查询。执行时,先执行子查询部分,求出子查询部分的值,再执行整个父查询,返回最后的结果。
    因为子查询作为WHERE条件的一部分,所以还可以和UPDATE,INSERT,DELETE一起使用,语法类似于SELECT语句。

    注意:
    将子查询和比较运算符联合使用,必须保证子查询返回的值不能多于一个!

    例如:

    #查询所有出生日期`bornDate`在小明之后的学生的信息
    SELECT * FROM `student` WHERE `bornDate` > 
    (SELECT `bornDate` FROM `student` WHERE `studentName` = '小明');
    

    IN和NOT IN子查询

    使用关键字IN可以使父查询匹配子查询返回的多个单字段值。

    IN子查询

    使用=,>等比较运算符时,要求子查询只能返回一条或空的记录。
    当子查询跟随在=,!=,<,<=,>,>=之后时,不允许子查询返回多条记录。

    当出现错误提示"Subquery returns more than 1 row"的意思是子查询返回值不唯一。这时只需将=改为IN即可,如下所示:

    SELECT `studentName` FROM `student`
    WHERE `studentNo` IN(
    	SELECT `studentNo` FROM `score`
    		WHERE `subjectNo` = (
    			SELECT `subjectNo` FROM `subject`
    			WHERE `subjectName` = 'Java'
    		)AND `studentScore` = 60
    );
    

    可以看出IN后面的子查询可以返回多条记录,用于限制学号的筛选范围。

    NOT IN子查询

    IN相反,这里就不做更多示范了。

    高级查询

    EXISTS和NOT EXISTS子查询

    EXISTS子查询

    在执行CREATE或DROP语句前,可以使用EXISTS语句判断数据库对象是否存在,返回值是TRUE或FALSE。例如,如果存在数据表temp,则先删除它,然后重新创建。

    DROP TABLE IF EXISTS temp;
    

    EXISTS也可以作为WHERE语句的子查询,基本语法如下:

    SELECT ... FROM 表名 WHERE EXISTS(子查询);
    

    EXISTS关键字后面的参数是一个任意的子查询,如果该子查询有返回行,则EXISTS子查询的结果为true,此时再执行外层查询语句。
    如果子查询没有返回行,则EXISTS子查询的结果为false,此时外层语句不再执行检查。

    NOT EXISTS子查询

    EXISTSIN一样,允许添加NOT关键字实现取反操作,NOT EXISTS表示不存在

    注意:
    EXISTSNOT EXISTS的结果只取决于是否有返回记录,不取决于这些记录的内容,所以EXISTSNOT EXISTS子查询后SELECT语句中的字段列表通常是无关紧要的。

    子查询注意事项

    注意事项

    在完成较复杂的数据查询时,经常会使用到子查询。编写子查询语句时,要注意以下事项:

    1.子查询语句可以嵌套在SQL语句中任何表达式出现的位置:
    SELECT语句中,子查询可以被嵌套在SELECT语句的列、表和查询条件中,即SELECT子句、FROM子句、WHERE子句、GROUP BY子句和HAVING子句。

    /*嵌套在SELECT语句的SELECT子句中的子查询语句如下*/
    SELECT (子查询) FROM 表名;
    /*注意:子查询结果为单行单列,但不必指定列别名。*/
    
    /*嵌套在SELECT语句的FROM子句中的子查询语句如下*/
    SELECT * FROM (子查询) AS 表的别名;
    /*注意:必须为表指定别名,一般返回多行多列数据记录,可以当作一张临时表。*/
    

    2.只出现在子查询中而没有出现在父查询中的表不能包含在输出列中
    多层嵌套子查询的最终数据集只包含父查询(即最外层的查询)的SELECT子句中出现的字段,而子查询的输出结果通常会作为其外层子查询数据源或用于数据判断匹配。

    常见错误:

    SELECT * FROM (SELECT * FROM `result`);
    /*这个子查询语句产生语法错误的原因在于,
    主查询语句中的 FROM 子句是一个子查询语句,因此应该为子查询结果集指定别名。
    正确代码如下:*/
    SELECT * FROM (SELECT * FROM `result`) AS Temp;
    

    分组查询

    使用GROUP BY进行分组查询

    比如,根据课程编号分组,求每门课程的平均分:

    SELECT `subjectNo`, AVG(`studentScore`) AS 课程平均成绩
    FROM `score`
    GROUP BY `subjectNo`;
    

    多列分组查询

    例如:统计不同年级的男,女学生人数。理论上先把每个学年分开,再针对每个学年,把男女学生人数各自统计,也就是需要按照两个列进行分组:年级,性别。

    SQL语句如下:

    SELECT COUNT(*) AS 人数, `grade` AS 年级, `sex` AS 性别 
    FROM `student`
    GROUP BY `grade`,`sex`
    ORDER BY `grade`;
    

    使用HAVING子句进行分组筛选

    WHERE子句只能对没有分组统计前的数据行进行筛选。
    对于分组后的条件的筛选必须使用HAVING子句。
    简单的说,HAVING子句用来对分组后的数据进行筛选,将"组"看作"列"来限定条件。

    例如:

    #查询年级总人数超过200人的年级
    SELECT COUNT(*) AS 人数, `gradeId` AS 年级 FROM `student`
    GROUP BY `gradeId`
    HAVING COUNT(*)>200;
    

    注意:
    HAVINGWHERE子句可以在同一个SELECT语句中一起使用,使用顺序如下:
    WHERE----->GROUP BY------->HAVING

    例如

    #查询有两个或两个以上员工工资不低于2000元的部门编号
    SELECT 部门编号, COUNT(*) FROM 员工信息表
    WHERE 工资 >= 2000
    GROUP BY 部门编号
    HAVING COUNT(*)>1;
    

    多表连接查询

    多表连接查询的分类

    1.内连接查询
    内连接查询是最典型、最常用的连接查询,它根据表中共同的列来进行匹配。特别是两个表存在外主键关系时通常会使用内连接查询。

    2.外连接查询
    外连接查询是至少返回一个表中的所有记录,根据匹配条件有选择性的返回另一张表的记录。外连接可以是左外连接、右外连接。

    内连接查询

    内连接查询通常会使用"=""<>"等比较运算符来判断两列数据值是否相等。
    求的是几个表满足条件的交集
    内连接使用INNER JOIN...ON关键字或WHERE子句来进行表之间的关联。内连接查询可以通过以下两种方式实现:

    1.在WHERE子句中指定连接条件
    例如,查询学生姓名和成绩的SQL如下:

    SELECT student.`studentName`, result.`subjectNo`,
    result.`studentResult` FROM student, result
    WHERE student.`studentNo` = result.`studentNo`;
    /*上面这种形式的查询,相当于FROM后面紧跟了两个表名,
    在字段列表中用"表名.列名"来区分列,
    再在WHERE条件子句中加以判断,要求学生编号信息相同。*/
    

    2.在FROM子句中使用INNER JOIN...ON

    上面的查询也可以用INNER JOIN...ON子句来实现,SQL如下:

    SELECT S.`studentName`, R.`subjectNo`, R.`studentResult`
    FROM student AS S
    INNER JOIN result AS R ON (S.`studentNo` = R.`studenNo`);
    /*
    1)INNER JOIN用来连接两个表
    2)INNER 可以省略
    3)ON 用来设置条件
    4)AS 指定表的别名。如果查询的列名在用到的两个表或多个表中不重复
    ,则对这一列的引用不必用表名来限定
    */
    

    查询科目编号为1的分数大于60分的学生的姓名和分数。WHERE子句限定查询条件。
    SQL如下:

    SELECT S.`StudentName`, R.`subjectNo`, R.`studentResult`
    FROM `student` AS S
    INNER JOIN result AS R ON (S.`StudentNo` = R.`StudentNo`)
    WHERE R.`score` > 60 AND R.`subjectNo` = 1;
    

    内连接查询可以查询多个表。如下SQL:

    SELECT S.`StudentName` AS 学生姓名
    , R.`subjectNo` AS 课程名称
    , R.`studentResult` AS 考试成绩
    FROM `student` AS S
    INNER JOIN `result` AS R ON (S.`StudentNo` = R.`StudentNo`)
    INNER JOIN `SUBJECT` AS SU ON (SU.`subjectNo` = R.`subjectNo`);
    

    外连接查询

    外连接查询中参与连接的表有主从之分,以主表的每行数据匹配从表的数据列,将符合连接条件的数据直接返回到结果集中;对那些不符合连接条件的列,将被填上NULL值后再返回到结果集中。

    1.左外连接查询

    左外连接查询的结果集包括LEFT JOIN子句中指定的左表的所有行,而不仅仅是连接列所匹配的行。若左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列均为空值。

    左外连接查询使用LEFT JOIN...ONLEFT OUTER JOIN...ON关键字来进行表之间的关联。

    例如:要统计所有学生的考试情况,要求显示所有参加考试学生的每次考试分数,没有参加考试的学生也要显示出来。这时候,以学生信息表为主表(有时也叫左表)、学生成绩表为从表的左外连接查询的SQL语句如下:

    SELECT  S.`StudentName`, R.`subjectNo`, R.`studentResult`
    FROM `student` AS S
    LEFT OUTER JOIN `result` AS R ON S.`StudentNo` = R.`StudentNo`;
    /*
    其中,从学生信息表中把每条记录跟成绩表的记录进行数据匹配。
    若成功,则返回到记录集。
    若不成功,则返回NULL值来进行填充记录集。
    如果有学生没参加考试,所以成绩表中没有相关的考试记录
    ,对应的科目编号和成绩以NULL填充进去。
    `student`表为左表
    `result`表为右表
    显示左表全部信息,右表显示与左表匹配成功的信息,没成功的就填NULL
    */
    

    2.右外连接查询

    右外连接查询与左外连接查询类似,只不过要包含右表中所有匹配的行。若右表中有的项在左表中没有对应的项,则以NULL填充。

    右外连接查询使用RIGHT JOIN...ON或者RIGHT OUTER JOIN...ON关键字来进行表之间的关联。例如,在某数据库中,存在书籍表Books和出版商表Publishers之间的右外连接将包括所有的出版商,在表Books中没有书名的出版商(很久没出书了)也会被列出。例如:

    SELECT Books.`Book_id`, Books.`book`, Publishers.`Pub_name`
    FROM `titles`
    RIGHT OUTER JOIN `Publishers` 
    ON Books.`Pub_id` = Publishers.`Pub_id`;
    

    UNION和UNION ALL操作符

    UNION 操作符

    UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
    简单来说就是将两张表在结果集中以上下的方式连接在一起,拼接成一张表(区别于内连接,左右连接,它们均为左右方向的连接)。

    注意:UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT语句中的列的顺序必须相同。

    UNION 语法:

    SELECT column_name(s) FROM table_name1
    UNION
    SELECT column_name(s) FROM table_name2
    #默认地 UNION 操作符选取不同的值 如果允许重复的值 请使用 UNION ALL
    

    UNION ALL 语法:

    SELECT column_name(s) FROM table_name1
    UNION ALL
    SELECT column_name(s) FROM table_name2
    /*UNION(UNION ALL) 结果集中的列名总是等于 
    UNION(UNION ALL) 中第一个 SELECT 语句中的列名*/
    

    例子1

    求出成绩各排名前五的男生和女生信息(成绩降序排列,且先女后男)
    表信息如下:

    id(pk int)sex(varchar)score(int)
    190
    291
    392
    493
    594
    695
    796
    890
    991
    1092
    1193
    1294
    1395
    1496

    SQL语句如下:

    (SELECT * FROM demo WHERE sex = '女' ORDER BY score DESC LIMIT 5)
    UNION ALL 
    (SELECT * FROM demo WHERE sex = '男' ORDER BY score DESC LIMIT 5)
    

    运行结果如下:

    idsexscore
    1496
    1395
    1294
    1193
    1092
    796
    695
    594
    493
    392

    例子2

    表信息:
    Employees_China表

    E_IDE_Name
    01Zhang, Hua
    02Wang, Wei
    03Carter, Thomas
    04Yang, Ming

    Employees_USA表

    E_IDE_Name
    01Adams, John
    02Bush, George
    03Carter, Thomas
    04Gates, Bill

    UNION命令列出中国美国的所有雇员名(重复项只显示一次)

    (SELECT E_Name FROM Employees_China)
    UNION
    (SELECT E_Name FROM Employees_USA)
    

    运行结果如下:

    E_Name
    Zhang, Hua
    Wang, Wei
    Carter, Thomas
    Yang, Ming
    Adams, John
    Bush, George
    Gates, Bill

    注意:这个命令无法列出在中国和美国的所有雇员。在上面的例子中,我们有两个名字相同的雇员,他们当中只有一个人被列出来了。UNION命令只会选取不同的值。


    UNION ALL命令:

    UNION ALL 命令和 UNION 命令几乎是等效的,不过 UNION ALL 命令会列出所有的值。

    实例:
    列出在中国和美国的所有的雇员(重复项就重复显示就可):

    (SELECT E_Name FROM Employees_China)
    UNION ALL
    (SELECT E_Name FROM Employees_USA)
    
    E_Name
    Zhang, Hua
    Wang, Wei
    Carter, Thomas
    Yang, Ming
    Adams, John
    Bush, George
    Carter, Thomas
    Gates, Bill

    SQL语句的综合应用

    暂无

    展开全文
  • 使用Java实现数据库编程学习总结 ——田超凡 一.数据库的设计 1.规范设计数据库的步骤: 收集信息、标识实体、标识实体属性、标识实体之间的关系 2.E-R图:实体——关系图(Entity-...

    使用Java实现数据库编程学习总结

                                         ——田超凡

    一.数据库的设计

    1. 规范设计数据库的步骤:

    收集信息、标识实体、标识实体属性、标识实体之间的关系

    2. E-R图:实体——关系图(Entity-Relationship),用来表示实体的组成部分和实体之间的关系。

    矩形名词代表实体,椭圆名词代表属性,菱形动词表示关系

    3. 数据库模型图UML:数据库模型图是在详细设计步骤时绘制的清晰表示各个实体(数据表),各个字段(列),标识了主外键关系的一个模型图,作用是更直观的展现数据库各个实体以及实体之间的关系。

    4. 映射基数:映射基数指的是各个数据实体之间的关联关系,常见映射基数有以下几种:

    一对一 1:1     一对多 1:N

    多对一 N:1     多对多 M:N

    5. 三大范式:三大范式(3NF)是规范设计数据库必须遵循的标准,是设计数据库的规范,其中三个范式的具体含义如下:

    第一范式(1NF):确保每列的原子性(每列都是不可再分的最小数据单元)

    第二范式(2NF):确保每列都和主键相关(每个表只描述一件事情)

    第三范式(3NF):每列都和主键直接相关,不能间接相关(除主键列以外的其他列不传递依赖于主键列)

    6. 三大范式对性能的影响:有时为了方便检索数据库中的数据,会在设计数据库时适当添加冗余字段,以空间换取时间。其次,在严格遵循使用三大范式设计数据库时会对数据库的性能产生影响。因此实际设计数据库时,既需要考虑三大范式,也需要考虑数据库的系统性能。

     

    二.初识MySQL

    1. MySQL是Oracle公司旗下的又一强大的关系型数据库,目前由企业版和社区版两种版本供用户下载使用。

    2. 安装MySQL需要遵循的步骤:

    ①官网下载MySQL,启动安装程序

    ②设置默认端口号,默认为3306,设置MySQL服务名,默认服务名为MySQL

    ③设置数据库默认字符集,默认选中latin1(ISO-8859-1),建议设置为utf8,对中文兼容性更好

    ④勾选安装时自动配置环境变量,也可在安装后手动像配置jdk一样配置MySQL环境变量

    ⑤选择安装路径,完成安装。

    3. 启动MySQL常用DOS命令

    ①启动MySQL服务

    net start mysql;

    ②关闭MySQL服务

    net stop mysql;

    ③登录MySQL服务器

    mysql -u root -p密码;

    mysql -u root -p;

    Enter password:输入密码

    ④退出MySQL服务器:

    exit;

    ⑤查看系统帮助

    HELP指令

    4. 回顾SQL语言(Struct Query Language)结构化查询语言

    SQL语言组成:

    DDL数据定义语言,定义数据库、表、约束

    DML数据操作语言:数据增删改

    DQL数据查询语言:数据查询

    DCL数据控制语言:权限的管理和回收等

    TCL事务控制语言:事务的处理(此处仅作了解)

     

    ①DDL数据定义语言:

    创建数据库:

    DROP DATABASE IF EXISTS 数据库名

    CREATE DATABASE 数据库名

    创建数据库表:

    DROP TABLE IF EXISTS 数据表名

    CREATE TABLE 表名

    (

    列名  数据类型  列的特征(null/not null),约束等

    )

    添加约束:

    ALTER TABLE 表名 ADD CONSTRAINT 约束名  约束类型  约束内容

     

    修改表结构:

    ALTER TABLE 表名 RENAME 新表名 (修改表名称)

    ALTER TABLE 表名 ADD 列名 数据类型 列的特征 (添加列)

    ALTER TABLE 表名 CHANGE 原列名 新列名 数据类型 列的特征(修改列名和列的特征)

    ALTER TABLE 表名 DROP COLUMN 列名 (删除列)

     

    DML数据操作语言:

    插入数据:

    ①一次插入一条记录

    INSERT INTO 表名(列名) VALUES (值)

    ②一次插入多条记录

    插入已存在表中:

    INSERT INTO 表名(列名) VALUES (值),(值),(值)....

    插入新表中:自动创建新表

    CREATE TABLE 表名 (SELECT 语句)

     

    修改数据

    UPDATE 表名 SET 列名=值 WHERE 更新条件

     

    删除数据

    DELETE FROM 表名 WHERE 删除条件

    清空表中数据

    TRUNCATE TABLE 表名

    DELETE FROM 表名

     

    DQL数据查询语言:

    SELECT 列名 FROM 表名

    WHERE 查询条件

    GROUP BY 分组

    HAVING 分组筛选

    ORDER BY 排序(ASC升序,默认值/DESC降序)

    LIMIT 行偏移量,行数

     

    DCL数据控制语言

    创建用户:

    CREATE USER 用户名

    IDENTIFIED BY 密码

    创建用户并授权:

    GRANT 权限 ON 数据库名.表名

    TO 用户名@`localhost`

    IDENTIFIED BY 密码

    修改用户密码:

    DOS命令:mysqladmin -u 用户名 -p password 新密码

    SQL命令:

    SET PASSWORD FOR 用户名@`localhost`=PASSWORD(新密码)

    删除用户:

    DROP USER 用户名1@`localhost`,用户名2@主机名

    查看所有用户:

    USE mysql;

    SELECT * FROM `user`;

     

     

    拓展SHOW语句

    ①查看所有数据库

    SHOW DATABASES;

    ②查看当前数据库的所有数据库表

    USE 数据库名;

    SHOW TABLES;

    ③查看默认字符集

    SHOW VARIABLES LIKE ‘character_set_%’

    ④查看表结构

    DESCRIBE 表名

    DESC 表名

    ⑤查看导出文件路径

    SHOW VARIABLES LIKE ‘secure%’

     

    三.子查询

    SELECT 列名 FROM 表名

    WHERE 列名=(子查询)

    注意:以上语句中的子查询只能返回唯一结果(因为使用的是关系运算符,关系运算符左右两边的值只能返回唯一结果),如果返回多条记录,将引发query more than 1 row异常

    IN/NOT IN子查询

    SELECT 列名 FROM 表名

    WHERE 列名 IN(子查询语句)/NOT IN(子查询语句)

    IN子查询作用:判断某列的值是否存在于某个范围内,类似于OR运算符的作用,IN后面子查询查询出的结果作为列举值并逐个与IN前面的列值判断,如果IN前面的列值为其中之一,则返回true,都不匹配返回false

     

    NOT IN运算符作用:进行IN子查询的取反操作,及如果如果IN前面的列值为子查询查询出的结果的其中之一,则返回false,都不匹配返回true

     

    EXISTS/NOT EXISTS子查询

    SELECT 列名 FROM 表名

    WHERE EXISTS (子查询)/NOT EXISTS(子查询)

     

    EXISTS作用:判断某列的值是否存在于子查询语句查询的结果中,仅判断是否存在。如果存在返回true,不存在返回false

    NOT EXISTS作用:作用同上,但是是对EXISTS的结果进行取反操作。即不存在返回true,存在返回false

     

    四:MySQL常用函数

    字符串函数:

    CONCAT()拼接

    UPPER()转换为大写

    LOWER()转换为小写

    SUBSTRING()截取字符串

     

    日期函数:

    NOW()当前系统日期和事件

    CURDATE()当前系统日期

    CURTIME()当期系统时间

    DATEDIFF()日期差

     

    数学函数:

    CEIL()向上取整

    FLOOR()向下取整

    ROUND()四舍五入

    RAND()返回0-1之间的随机数

     

    五.事务、视图、索引、备份和恢复、数据导入和导出

    事务:事务是一个整体,必须同时执行,要么成功,要么失败,从而保证数据库中数据状态一致。

    事务的特性(ACID):

    原子性:事务是不可再分的最小逻辑工作单元,必须同时执行,要么全部执行,要么都不执行。

    一致性:事务在开始前和提交回滚后,数据库中的数据保持一致状态。

    隔离性:事务和事务之间相互独立,互不干涉。

    持久性:事务成功提交或回滚后,对数据库数据造成的影响是持久的。

    语法:

    开启事务

    BEGIN;

    START TRANSACTION;

    提交事务

    COMMIT;

    回滚事务

    ROLLBACK;

     

    视图:视图可以理解为虚拟表,是表数据的引用。视图可以互相嵌套,主要用来做查询,可以增删改数据,将会同步引用的表的数据。

    创建视图:

    CREATE VIEW 视图名

    删除视图

    DROP VIEW 视图名

    查看视图

    SELECT * FROM view_name

     

    索引:索引用来提高数据检索速度,提高数据查询的性能。

    索引类型:普通索引、主键索引、全文索引、空间索引、唯一索引、组合索引。

    创建索引

    CREATE (UNIQUE/FULLTEXT/SPATIAL) INDEX index_name

    ON table_name(column_name)

    删除索引

    DROP INDEX index_name FROM table_name

    查看索引

    SHOW INDEX FROM table_name

     

    备份和恢复:

    备份数据库

    DOS命令: mysqldump -u root -p密码 数据库名 > 文件名

    恢复数据库

    DOS命令: mysql -u root -p密码 数据库名 < 文件名

    SQL命令:

    USE 数据库名;

    SOURCE 数据库备份文件名

     

    导出数据:

    SELECT ...INTO OUTFILE 文件名

    导入数据:

    LOAD DATA INFILE 文件名 INTO TABLE 表名

     

    六.JDBC

    1.JDBC:Java连接数据库技术,全程Java DataBase Connectivity

    2.JDBC API:使用JDBC常用接口访问和操作数据库

    3.使用JDBC访问和操作数据库步骤(纯Java方式)

    首先在项目中Build Path MySQL数据库JAR包

    ①加载驱动Class.forName(“com.mysql.jdbc.Driver”);

    ②获取链接

    Connection conn=DriverManager.getConnection(“jdbc:mysql://localhost:3306/数据库名”,”root”,”root”);

    参数:连接字符串、用户名、密码

    ③获取Statement或PreparedStatement接口实例

    Statement stmt=conn.createStatement();

    PreparedStatement pstmt=conn.preparedStatement(sql语句);

    ④编写SQL语句

    ⑤调用Statement或PreparedStatement接口方法执行数据库操作

    boolean execute()查询SQL返回true,其他SQL返回false

    Int executeUpdate()执行增删改,返回受影响的行数Int类型

    ResultSet executeQuery()执行查询,返回查询结果集ResultSet对象

    ⑥处理查询结果

    resultSet.next() 前进到下一行记录中,读到记录返回true,没有读到记录返回false

    getXX()获取每行记录中每列的值

    ⑦关闭连接,释放资源

    先关闭ResultSet,在关闭Statement或PreparedStatement,最后关闭Connection,注意checked异常处理。

     

    七.DAO模式

    数据持久化:数据持久化就是将程序中的数据在瞬时状态和持久状态之间相互转换的机制。

    DAO层:数据访问层,负责实现数据持久化,对数据库数据的增删改查,降低代码耦合度,提高内聚性。

    DAO模式组成:

    DAO接口、DAO接口实现类、Entity实体类,BaseDao数据库链接和关闭工具类

    Properties类:负责读取数据库配置文件中的驱动、连接字符串、用户名、密码等数据库参数信息

    读取步骤:

    ①创建Properties类的实例

    Properties properties=new Properties();

    ②将配置文件读入InputStream流

    InputStream inputStream=BaseDao.class.getClassLoader().getResourceAsStream(“配置文件名”);

    ③调用Properties类实例的load()方法读取流

    Properties.load(inputStream);//.注意处理checked异常

    ④调用Properties类的实例的getProperty(String key)方法根据配置文件中的key映射获取到相应的value值

    String driver=properties.getProperty(“driver”);

    ....

    实体类标准定义:

    ①类名public

    ②属性private

    ③属性名和映射表的字段名尽量保持一致,采用驼峰命名法。

    ④提供公有的getter/setter方法封装属性

    ⑤最好实现java.io.Serializable接口,支持序列化机制。

     

    注意:转载请注明原作者

    展开全文
  • vc数据库编程三部教学(visual c++ 6.0 数据库高级编程)例程所需数据库。可以省去不少建立数据库的时间
  • Matlab数据库编程指南

    千次阅读 2011-11-04 10:59:09
    Matlab与数据库链接有三种方法,本文只讲述其中以ODBC的方式进行链接。 本文件包含四部分,其中第三部分为我自己写的一些数据库函数操作的函数,第四部分为网上的一些资料。 如有疑问可以邮件联系 tntuyh@163.com...
  • 使用Java实现数据库编程(第一章)

    千次阅读 2018-04-18 15:06:29
    第一范式 属性不可再分 原子性 ...只有低级冗余才会增加数据的不一致性,因为同一数据,可能从不同时间、地点、角色上多次录入。因此,我们提倡高级冗余(派生性冗余),反对低级冗余(重复性冗余)
  • c语言数据库编程--ODBC

    千次阅读 2012-09-07 09:55:27
    c语言数据库编程 转载自:http://www.cnblogs.com/nliao/archive/2010/09/09/1822660.html   最近我的导师要求我用c语言读出access数据库的数据,我四处查找资料,终于找到了实现的办法,那就是odbc api编程。...
  • 编程语言与数据库

    千次阅读 2018-07-21 12:25:58
    从新近的TIOBE编程语言排名可看到,Java、C依然稳定地在最受欢迎前列。 因具备图灵完备性,2018年才重新被纳入清单的SQL语言已快速出现在第9位置(7月)——这似乎意味着,传统的RDBMS(关系数据库系统)仍然是应用...
  • 前文分享了Python网络攻防相关基础知识,包括正则表达式、Web编程和套接字通信,本文将继续分析Python攻防之多线程、C段扫描和数据库编程。本文参考了爱春秋ADO老师的课程内容,这里也推荐大家观看他Bilibili和...
  • 数据库编程

    千次阅读 2017-08-06 22:13:52
    (b) 请用sql语句把张三的时间更新成为当前系统时间 (c) 请写出删除名为张四的全部记录 解答: (a)insert into user values('小王','13254748547','高中毕业','2007-05-06');  (b)UPDATE `user` set ...
  • 我们是先设计好数据表,再使用开发语言建立对应的数据模型,不过,我们今天要讲的是一个逆向操作的过程,即如何通定义GORM框架的数据模型,然后再通过执行GROM框架编写的应用程序,用定义好数据模型在数据库中创建...
  • 编程语言与数据库的关系

    万次阅读 2017-05-21 07:22:13
    前台的用户界面是用编程语言实现的,后台的数据存储是由数据库管理系统承载的。编程语言与数据库管理系统就好比是信息管理系统的两个轮子,是一张扑克的正反面,是一台戏的前台和后台,是一场演唱会的演员和乐队,是...
  • 数据库编程总结

    万次阅读 热门讨论 2010-04-11 20:10:00
    数据库编程总结当前各种主流数据库有很多,包括Oracle, MS SQL Server, Sybase, Informix, MySQL, DB2, Interbase / Firebird, PostgreSQL, SQLite, SAP/DB, TimesTen, MS ACCESS等等。数据库编程是对数据库的创建、...
  • MFC+Access数据库(ADO数据库编程

    千次阅读 2016-04-05 13:17:03
    顺带提一句,本文使用的系统为win8.1,64位,编译环境为VS2010和office2010,如出现连接问题,可以看看Access的位数与系统位数是否一致。 本文是在ADO(Microsoft Active Data Objects)接口下对数据库进行操作的。
  • 让你在短时间内了解在delphi中如何连接和使用数据库
  • 数据库编程项目命名规范

    千次阅读 2018-03-02 22:31:36
    数据库命名设计规范 1.数据库涉及字符规范 采用26个英文字母(区分大小写)和0-9这十个自然数,加上下划线'_'组成,共63个字符.不能出现其他字符(注释除外)。 注意事项: 1)以上命名都不得超过30个字符的系统限制.变量名...
  • 1. 第10章 数据库编程课件( PPT , PDF ),请特别关注最后P16-20页,讲MySQL的部分。 2. MySQL安装包mysql-5.5.12-win32.rar( 下载 ),适合32位系统,解压缩后运行 mysql-5.5.12-win32.msi, 安装过程图解 ...
  • 数据库实验——T-SQL编程

    千次阅读 2019-07-11 12:43:12
    一、实验目的 1.掌握各种运算符和控制语句的使用; 2.掌握系统函数的使用; 3.掌握存储过程的实现。 ...1.了解T-SQL支持的各种基本数据类型...以实验数据库为基础数据,完成以下内容 1.变量的使用 (1)创建局部变...
  • MySQL数据库教程之七:MySQL编程基础

    千次阅读 2020-03-29 13:08:37
    MySQL数据库教程之七:MySQL编程基础 准备工作: 先启动MySQL,并打开前期建立的数据库和表 查看每个表的结构: 一、MySQL常量的基本编程 按照MySQL的数据类型划分,可以划分为:数值常量、字符串常量...
  • QT编程中mysql数据库时间、日期的运用初次接触QT,感觉很不适应,无论是安装还是编程,并且入门感觉好麻烦,各种乱码、报错,而且相同的错误可能换换电脑就正常了。可能由于我不了解C++的缘故,在一个需求中要比较...
  • 日期和时间是每个系统,每个数据库设计必不可少的部分。也是容易被大家忽视的部分...最近设计新系统的数据库,涉及到跨时区的问题,于是专门调研了不同日期时间类型的利弊,也咨询了不少同行使用的情况。这里分享给大家
  • 为了提升系统访问数据库的性能,可以事先创建若干连接置于连接池中,需要时直接从连接池获取,使用结束时归还连接池而不必关闭连接,从而避免频繁创建和释放连接所造成的开销,这是典型的用空间换取时间的策略(浪费...
  • ssm java编程遇到从数据库中查询的时间与存储时间不一致推荐先去看这篇文章: java编程中遇到的时区与时间问题总结 http://blog.csdn.net/yeahwell/article/details/8559996 这几天开发中遇到一个问题:ssm中使用...
  • Python实现数据库编程方法详解

    千次阅读 2016-10-20 22:05:11
    这篇文章主要介绍了Python实现数据库编程方法,较为详细的总结了Python数据库编程涉及的各种常用技巧与相关组件,需要的朋友可以参考下 本文实例讲述了Python实现数据库编程方法。分享给大家供大家参考。具体...
  • 第一次写这个感到有点不知所措,还好去图书馆找来本关于ASP.NET数据库编程的书,看看弄弄还是有点成果了。遇到些问题:1、数据库连接不上,先后报错40,26。搜索网上的资料,找到解决方法:开启远程,配置用户。链接...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 489,287
精华内容 195,714
关键字:

数据库编程时间问题