SQL学习笔记

一、QT  SQL

    #include <QSqlDatabase>
    #include <QSqlError>
    #include <QSqlQuery>


    QSqlDatabase database;
    QString DBPath = QCoreApplication::applicationDirPath();
    DBPath += "\\database\\punch.db";

    //检查指定的连接(qt_sql_default_connection)是否存在
    if(QSqlDatabase::contains("qt_sql_default_connection")){
       database = QSqlDatabase::database("qt_sql_default_connection");
    }else{
        //创建连接
        database = QSqlDatabase::addDatabase("QSQLITE");//设置数据库驱动名称
        database.setDatabaseName(DBPath);//若数据库不存在则建立该数据库
        //database.setUserName("root");
        //database.setPassword("root");
    }


    if(!database.open()){ 
       QMessageBox box(QMessageBox::Question,"提示",database.lastError().text());
       box.exec();  
    }

二、SQL常见语法

1.创建表

create table 表名称
(
列名称1 数据类型,
列名称2 数据类型,
列名称3 数据类型,
....
)

SQL NOT NULL 约束

NOT NULL 约束强制列不接受 NULL 值。

NOT NULL 约束强制字段始终包含值。这意味着,如果不向字段添加值,就无法插入新记录或者更新记录。

下面的 SQL 语句强制 "Id_P" 列和 "LastName" 列不接受 NULL 值:

 
 

2.读入数据

代码如下(示例):

data = pd.read_csv( 'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv') print(data.head()) 

该处使用的url网络请求的数据。


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法

删除表:            drop  table 表名;             

插入数据:       insert  into 表名 values(, , ,) ;  

创建索引:       create [unique] index 索引名on 表名(col….);

删除索引:   drop index 索引名(索引是不可更改的,想更改必须删除重新建)
删除数据:       delete from 表名;             

更新数据:       update 表名 set 字段=’修改后的内容’ where 条件;

增加一个列:  Alter table 表名 add column 字段 数据类型; 

选择查询:       select 字段(以”,”隔开) from 表名 where 条件;

日期和时间: Select datetime('now')

日期:   select date('now');       
时间:  select time('now');  

总数select count(*) from table1;
求和select sum(field1) from table1;
平均select avg(field1) from table1;
最大select max(field1) from table1;
最小select min(field1) from table1;

排序select 字段 from table1 order by 字段(descasc)  ;(降序或升序)

分组select 字段 from table1 group by 字段,字段  ;

限制输出:select 字段fromtable1 limit x offset y;

                          = select 字段 from table1 limit y , x;

(备注:跳过y行,取x行数据)

 (

QT使用Sqlite3

QT读写Sqlite数据库的三种方式

QT SQlite用法

QSqlQuery

可以用来执行SQL语句和获得执行结果的。

QSqlQueryModel

提供了一个sql查询结果的只读数据模型。它从查询QSqlQueryModel获取数据。

可以方便的用于在QListView, QTableView, QTreeView等各种view上展示数据。

但它是只读的,不能编辑。

QSqlTableMode

继承于QSqlQueryModel,与QSqlQueryModel功能相似。

比QSqlQueryModel的限制在于不能是任意sql语句,只是对单个数据表操作。

拓展在于在各种view上展示表格数据的同时,还允许用户进行编辑操作。

2.创建表名

  • NOT NULL 约束:确保某列不能有 NULL 值。

  • CREATE TABLE COMPANY(
       ID INT PRIMARY KEY     NOT NULL,
       NAME           TEXT    NOT NULL,
       AGE            INT     NOT NULL,
       ADDRESS        CHAR(50),
       SALARY         REAL
    );
  • DEFAULT 约束:当某列没有指定值时,为该列提供默认值。

  • CREATE TABLE COMPANY(
       ID INT PRIMARY KEY     NOT NULL,
       NAME           TEXT    NOT NULL,
       AGE            INT     NOT NULL,
       ADDRESS        CHAR(50),
       SALARY         REAL    DEFAULT 50000.00
    );
    REAL 在无数据插入时默认为50000.00
  • UNIQUE 约束:确保某列中的所有值是不同的。

  • CREATE TABLE COMPANY(
       ID INT PRIMARY KEY     NOT NULL,
       NAME           TEXT    NOT NULL,
       AGE            INT     NOT NULL UNIQUE,
       ADDRESS        CHAR(50),
       SALARY         REAL    DEFAULT 50000.00
    );  
    AGE变唯一,不能出现重复AGE
  • PRIMARY Key 约束:唯一标识数据库表中的各行/记录。

  • CREATE TABLE COMPANY(
       ID INT PRIMARY KEY     NOT NULL,
       NAME           TEXT    NOT NULL,
       AGE            INT     NOT NULL,
       ADDRESS        CHAR(50),
       SALARY         REAL
    );

    在一个表中可以有多个 UNIQUE 列,但只能有一个主键

  • CHECK 约束:CHECK 约束确保某列中的所有值满足一定条件。

CREATE TABLE COMPANY3(
   ID INT PRIMARY KEY     NOT NULL,
   NAME           TEXT    NOT NULL,
   AGE            INT     NOT NULL,
   ADDRESS        CHAR(50),
   SALARY         REAL    CHECK(SALARY > 0)
);
REAL 只能插入大于0的值

创建表名 student 主键为 id  负键name age score

CREATE TABLE student (id integer PRIMARY KEY, name text,age integer,score real);

如果不存在就创建

CREATE TABLE IF NOT EXISTS student (id integer PRIMARY KEY, name text,age integer,score real);

创建表 主键自动增长

CREATE TABLE IF NOT EXISTS student (id integer PRIMARY KEY AUTOINCREMENT, name text,age integer,score real);



 

QSqlQuery sql_query;
sql_query.exec("CREATE TABLE IF NOT EXISTS student (id integer PRIMARY KEY, name text,age integer,score real)")

id integer PRIMARY KEY AUTOINCREMENT 自增长主键问题

在用sqlite设计表时,突然想到一个问题,就是我设计的表中,每个表都有一个自己的整形id值作为主键,其实可以不指定这么一个id值,sqlite内部本来就会为每个表加上一个 rowid,这个rowid可以当成一个隐含的字段使用,但是由sqlite引擎来维护的,在3.0以前rowid是32位的整数,3.0以后是64位的整数,为什么不直接使用这个内部的rowid作为每个表的id主键呢。

想到就立即先查找一下sqlite的文档,看看用指定INTEGER PRIMARY KEY AUTOINCREMENT 和不指定自增长字段用rowid有什么区别。相关的文档在这里:
SQLite Autoincrement
SQLite Frequently Asked Questions

使用自增长字段为主键有不少问题,比如维护或是在大型分布应用中主键冲突的解决等。在一些大型分布应用中主键一般选用guid,这可以有效的避免主键冲突,减少对主键维护的工程。当然,对于中小型的应用,自增长字段的好处更多一些,简单、快速。

Sqlite中,一个自增长字段定义为INTEGER PRIMARY KEY AUTOINCREMENT        ,那么在插入一个新数据时,只需要将这个字段的值指定为NULL,即可由引擎自动设定其值,引擎会设定为最大的rowid+1。当然,也可以设置为非NULL的数字来自己指定这个值,但这样就必须自己小心,不要引起冲突。当这个rowid的值大于所能表达的最大值9223372036854775807 (3.0及以后版本的rowid最大值)后,rowid的新值会这个最大数之前随机找一个没被使用了的值。所以在rowid达到最大值前,rowid的值是严格单调增加的。

INTEGER PRIMARY KEY AUTOINCREMENT 自增长字段的算法与rowid稍微有些不同。


第一,在达到最大值后,rowid会找已被删除的字段对应的rowid作为新值,而自增长字段则会丢出一个SQLITE_FULL的错误。

第二,自增长字段在增加新值时,是找一个从没被使用过的rowid作为新值,而rowid则是找最大已存在的rowid+1。这里对应用的影响会比较大,尤其是一些对id值有依赖的元记录,只适合使用自增长字段而不能用rowid。
比如,我们设计一个元记录表:

Create table meta_struct(id INTEGER PRIMARY KEY AUTOINCREMENT, name varchar, type Integer);


然后,定义一个一级表,来描述其它表的结构:


Create table meta_table(tableid INTEGER, table_field integer)

最后,我们的应用可以根据这个一级表来产生实际使用的二级表。
这样为保证兼容性meta_struct中的id必须是唯一的,如果有字段被删除,也不能重复使用这个字段的id值,不然,在数据库合并时,一级表和二级表就会混乱。所以meta_struct表中的主键只能使用自增长字段,而不能用rowid。

第三,使用自增长字段,引擎会自动产生一个sqlite_sequence表,用于记录每个表的自增长字段的已使用的最大值,用户可以看到,并可以用使用Update、Delete和Insert操作,但不建议这么使用,这会让引擎混乱。如果使用rowid,也会有这么一个内部表,用户可以维护rowid值,但看不到。

这么看来,如果直接使用rowid来代替自增加字段,根据两者的细微的差别,需要注意是否与自己的应用冲突,如果没有冲突,那么用rowid会更快一点。

1增

1.1【插入单行】
insert [into] <表名> (列名) values (列值)
例:insert into Strdent (姓名,性别,出生日期) values ('开心朋朋','男','1980/6/15')

例2:  INSERT INTO student VALUES(19, \"Li\", 23)

1.1【插入单列】

SQLite的alter不支持添加多列

ALTER TABLE mytable ADD time TEXT 

ALTER TABLE mytable ADD source INTEGER DEFAULT 0


1.3【将现有表数据添加到一个已有表】
insert into <已有的新表> (列名) select <原表列名> from <原表名>
例:insert into czp('姓名','地址','电子邮件')
select name,address,email
from Strdent


1.4【直接拿现有表数据创建一个新表并填充】
select <新建表列名> into <新建表名> from <源表名>
例:select name,address,email into czp from Strdent


1.5【使用union关键字合并数据进行插入多行】
insert <表名> <列名> select <列值> union select <列值>
例:insert Student (姓名,性别,出生日期)
select '开心朋朋','男','1980/6/15' union(union表示下一行)
select '蓝色小明','男','19**/**/**'

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

2删

2.1【删除<满足条件的>行】
delete from <表名> [where <删除条件>]
例:delete from Student where name='开心朋朋'(删除表Student 中列值为开心朋朋的行)


2.2【删除整个表】 //sqlite3 无
truncate table <表名>
truncate table Student
注意:删除表的所有行,删除速度比delete快,但表的结构、列、约束、索引等不会被删除;不能用语有外建约束引用的表

2.3【删除表】

drop table <表名>

drop table Student

用于删除表(表的结构、属性以及索引也会被删除);


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

3改

update <表名> set <列名=更新值> [where <更新条件>]
例:update czp set 年龄=18 where 姓名='蓝色小名'


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

4查

where子句操作符

  • 操作符兼容。表中所列出的操作符是冗余的,有功能相同的操作符。具体DBMS支持的操作符不一样。
  • 经过尝试,MySQL中除不支持!<、!>这两个操作符外,其他都支持。
  • SQL过滤或在应用层过滤?通常最好选择SQL过滤。
  • 字符串类型的列进行比较,需要限定引号  ' awe0235  ' 。值与数值列进行比较,则不用引号。

!=  ,<> , IS NOT      作用一致

 AND、OR、IN、NOT四种操作符

1. 优先级:圆括号 > AND > OR。在三者中圆括号的优先级最高。

2. 任何时候使用具有AND和OR操作符的WHERE子句,都应该使用圆括号明确地分组操作符。

AND 和

OR  或

IN   IN ( 25, 27 )相当于AGE  = 25 OR  27

NOT 不

WHERE AGE >= 25 AND SALARY >= 65000            列出了 AGE 大于等于 25 SALARY 大于等于 65000.00

WHERE AGE IS NOT NULL                                       列出了 AGE 不为 NULL 的所有记录

WHERE AGE IS NULL                                           列出了 AGE 为 NULL 的所有记录

WHERE AGE  IN ( 25, 27 )                                 列出了 AGE 的值为 25 或 27 的所有记录

WHERE AGE  IS  NOT IN ( 25, 27 )                                 列出了 AGE 的值既不是 25 也不是 27 的所有记录

WHERE AGE BETWEEN 25 AND 27                        列出了 AGE 的值在 25 与 27 之间的所有记录,包括25和27WHERE ID NOT IN   (select ID from AGE WHERE ID > 11 AND ID < 100) 列出 AGE表中 ID 不是在10~100之间的所有值。

Like 子句 

(—) 代表位

(%) 代表 以什么什么开头 或结尾

语句描述
WHERE SALARY LIKE '200%'查找以 200 开头的任意值
WHERE SALARY LIKE '%200%'查找任意位置包含 200 的任意值
WHERE SALARY LIKE '_00%'查找第二位和第三位为 00 的任意值
WHERE SALARY LIKE '2_%_%'查找以 2 开头,且长度至少为 3 个字符的任意值
WHERE SALARY LIKE '%2'查找以 2 结尾的任意值
WHERE SALARY LIKE '_2%3'查找第二位为 2,且以 3 结尾的任意值
WHERE SALARY LIKE '2___3'查找长度为 5 位数,且以 2 开头以 3 结尾的任意值

GLOB有大小写区分 必须大写

(?) 代表位

(*) 代表 以什么什么开头 或结尾

语句描述
WHERE SALARY GLOB '200*'查找以 200 开头的任意值
WHERE SALARY GLOB '*200*'查找任意位置包含 200 的任意值
WHERE SALARY GLOB '?00*'查找第二位和第三位为 00 的任意值
WHERE SALARY GLOB '2??'查找以 2 开头,且长度至少为 3 个字符的任意值
WHERE SALARY GLOB '*2'查找以 2 结尾的任意值
WHERE SALARY GLOB '?2*3'查找第二位为 2,且以 3 结尾的任意值
WHERE SALARY GLOB '2???3'查找长度为 5 位数,且以 2 开头以 3 结尾的任意值

Limit 子句 

sqlite> SELECT * FROM COMPANY LIMIT 3 OFFSET 2;

抵消2行 取出3行   意思从第3行开始,包括第三行 ,接下来的三行。

Distinct 关键字

消除所有重复的记录

SELECT DISTINCT name FROM COMPANY;

显示name列 并去除重复数据

4.1精确(条件)查询

语法: select <列名> from <表名> [where <查询条件表达试>] [order by <排序的列名>[asc或desc]]

4.1.1【查询所有数据行和列】
例:select * from a
说明:查询a表中所有行和列

4.1.2【查询部分行列--条件查询】
例:select i,j,k from a where f=5
说明:查询表a中f=5的所有行,并显示i,j,k3列

4.1.3【在查询中使用AS更改列名】
例:select name as 姓名 from a where xingbie='男'
说明:查询a表中性别为男的所有行,显示name列,并将name列改名为(姓名)显示

4.1.4【查询空行】
例:select name from a where email is null
说明:查询表a中email为空的所有行,并显示name列;SQL语句中用is null或者is not null来判断是否为空行

4.1.5【在查询中使用常量】
例:select name, '唐山' as 地址 from Student
说明:查询表Student,显示name列,并添加地址列,其列值都为'唐山'

4.1.6【查询返回限制行数(关键字:top percent)】
例1:select top 6 name from a
说明:查询表a,显示列name的前6行,top为关键字
例2:select top 60 percent name from a
说明:查询表a,显示列name的60%,percent为关键字

4.1.7【查询排序(关键字:order by , asc , desc)】
例:select name from a where chengji>=60 order by desc
说明:查询a表中chengji大于等于60的所有行,并按降序显示name列;默认为ASC升序

按列n2的升序排列

select * from a order by n2 asc;

按列n2的降序排列

select * from a order by n2 desc;

4.1.8 【复合排序】

select * from a id order by id desc limit 0,1

order by id desc是按id进行降序排列
limit 0,1 是只取记录中的第一条.
所以这条语句只能得到一条记录
如想取前10条则 limit 0,10或limit 10
如想取第10至20条则 limit 10,20


4.2模糊查询


4.2.1【使用like进行模糊查询】
注意:like运算符只用于字符串,所以仅与char和varchar数据类型联合使用
例:select * from a where name like '赵%'
说明:查询显示表a中,name字段第一个字为赵的记录

4.2.2【使用between在某个范围内进行查询】
例:select * from a where nianling between 18 and 20
说明:查询显示表a中nianling在18到20之间的记录

4.2.3【使用in在列举值内进行查询】
例:select name from a where address in ('北京','上海','唐山')
说明:查询表a中address值为北京或者上海或者唐山的记录,显示name字段


4.3.分组查询


4.3.1【使用group by进行分组查询】
例:select studentID as 学员编号,AVG(score) as 平均成绩 from Student group by studentID
说明:在表Student 中查询,按strdentID列分组,显示strdentID列   score列的平均值;select语句中只允许被分组的列和为每个分组返回的一个值的表达式

4.3.2【使用having子句进行分组筛选】
例:select studentID as 学员编号,AVG(score) as 平均成绩 from Student group by studentID having count(score)>1
说明:在表Student 中查询,显示分组后count(score)>1的行,由于where只能在没有分组时使用,分组后只能使用having来限制条件。

内连接与外连接的区别


--表stu
id  name  
1,  Jack
2,  Tom
3,  Kity
4,  nono
--表exam
id   grade
1,   56
2,   76
11,  89

内连接 (显示两表id匹配的)
select stu.id,exam.id,stu.name, exam.grade from stu inner join exam on stu.id=exam.id
stu.id   exam.id  name     grade
--------------------------------
1 1 Jack 56
2 2 Tom 76

左连接(显示join 左边的表的所有数据,exam只有两条记录,所以stu.id,grade 都用NULL 显示)
select stu.id,exam.id,stu.name, exam.grade from stu left join exam on stu.id=exam.id
1  1       Jack    56
2  2       Tom    76
3  NULL Kity     NULL
4  NULL nono  NULL

右连接(与作连接相反,显示join右边表的所有数据)
select stu.id,exam.id,stu.name, exam.grade from stu right join exam on stu.id=exam.id
1        1   Jack   56
2        2   Tom   76
NULL 11  NULL 89

来自百度知道。。。。


4.4.多表联接查询

4.4.1内联接

【在where子句中指定联接条件】
例:select a.name,b.chengji   from a,b  where a.name=b.name

或:select a.name,b.chengji   from a inner join b on (a.name=b.name)

说明:查询表a和表b中name字段相等的记录,并显示表a中的name字段和表b中的chengji字段(只显示表a和表b中name字段相等的行)

例子:(AS 作为修改表或列的名字)

S.SName AS 姓名, CS.CourseName AS 课程, C.Score AS 成绩

FROM Students AS S

INNER JOIN Score AS C ON (S.SCode = C.StudentID)

INNER JOIN Course AS CS ON (CS.CourseID = C.CourseID

4.4.2外联接

left outer join 等价于left  join                    左外连接和左连接  写法不同   概念相同

4.4.2.1【左外联接查询】

left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录  


1.如果想全量显示aa 表中的内容:

例: Select * From aa left outer join bb on aa.id=bb.id

2.显示c中某几列  显示b中联结字段相等的记录

例:select b.scode,c.core from c  left outer join b  on b.scode=c.strdentID

3.显示a中某几列  显示b和c中联结字段相等的记录

例:select a.name,b.scode,c.core from a  left outer join b  on b.scode=c.strdentID

说明:查询表b中scode字段和表c中strdentID字段相等的记录,并显示表a中的name字段所有行 和表b中的scode字段(只显示表b中scode字段相等的行)和表c中的core 字段(只显示表c中strdentID字段相等的行)?有待验证

外连接(OUTER JOIN)是内连接(INNER JOIN)的扩展。虽然 SQL 标准定义了三种类型的外连接:LEFT、RIGHT、FULL,但 SQLite 只支持 左外连接(LEFT OUTER JOIN)

4.4.2.2【右外联接查询】

select b.scode,c.core from c  left outer join b  on b.scode=c.strdentID

将左联接 中 from c  left outer join b  改为from b  left outer join c  这就相当于右联接

4.4.2.3【全联接查询】

如果想两张表都能全量显示,将以上两个结果合并。即:先以AA表执行一条左外连接,再以BB表执行一条左外连接:
Select aa.*,bb.* from aa left outer join bb on aa.id=bb.id
union
select aa.*,bb.* from bb left outer join aa on aa.id=bb.id ?有待验证

SQLite3中的三种Join方式

前一阵子设计数据库结构,有个设计是要保存所有的音、视频和图片信息的metadata到表中,并要求可以不分类型的一次全部检索出来。原来有个设计是设计一张大表,把所有的字段不分类型全都添进去,通过类型字段进行判断,读取哪些metadata作为检索结果。这样就导致表的结构十分复杂,且大量的字段为空。为了解决这个问题,查了一下SQL的Join算法,解决了这个设计问题。以下是SQLite3中支持的Join方式及使用说明:

1. Cross Join

又叫笛卡尔积,匹配前一个表与后一个表的每一行和每一列,这样得到的结果集为n*m行(n, m分别为每张表的行数),x+y列(x, y分别为每张表的列数)。可见,该结果集可能会成为一个巨大的表,对内存和后续处理都会造成巨大压力,所以,慎用(真没用过)。

语法:SELECT ... FROM t1 CROSS JOIN t2 ...

2. Inner Join

类似Cross Join,但内建机制限制了返回的结果数量。返回的结果集不会超过x + y列,行数在0- n*m行之间。有3种方法用来指定Inner Join的判断条件:

第一种是On表达式:SELECT ... FROM t1 JOIN t2 ON conditional_expression ...,例如:SELECT ... FROM employee JOIN resource ON employee.eid = resource.eid ...。

但On这种方式有俩个问题:一是语句比较长,二是存在重复列,如俩个eid。因此,可以使用第二种方式Using表达式:SELECT ... FROM t1 JOIN t2 USING ( col1 ,... ) ...,这种Join返回的结果集中没有重复的字段,只是每个字段必须存在于各个表中。

更简洁的方式是,使用第三种方式Natural Join:SQL自动检测各表中每一列是否匹配,这样,即使表结构发生变化,也不用修改SQL语句,可以自动适应变化。

3. Outer Join

解决我的问题使用的是Outer Join。

SQLite3只支持left outer join,其结果集由不大于x + y列,n - n*m行构成,至少包含左侧表的每一行,对于Join后不存在的字段值,则赋NULL。这样得到的表与我们之前设计那个全集结果一样,但数据结构更清晰,空间占用更少。

4.5子查询

子查询或内部查询或嵌套查询是另一个SQLite查询和嵌入在WHERE子句中的查询。

使用子查询返回的数据将被用来在主查询中作为条件,以进一步限制要检索的数据。

可以使用子查询的SELECT,INSERT,UPDATE和DELETE语句,随着运算符如=,<,>,>=,<=,IN,BETWEEN等

有几个子查询必须遵循的规则:

  • 必须用括号括起来的子查询。

  • 子查询只能有一个在SELECT子句中的列,除非多列在主查询的查询来比较其选定的列。

  • 一个ORDER BY不能使用在子查询中,虽然主要的查询就可以使用ORDER BY。使用GROUP BY可以用来执行相同的功能在子查询中的ORDER BY。

  • 只能用于使用多值运算符,如IN操作符子查询返回多于一行。

  •  BETWEEN 运算符不能用子查询,然而,BETWEEN 可以在子查询中使用。

SELECT语句中的子查询使用:

最常用的子查询的SELECT语句。基本语法如下:

SELECT column_name [, column_name ]
FROM   table1 [, table2 ]
WHERE  column_name OPERATOR
      (SELECT column_name [, column_name ]
      FROM table1 [, table2 ]
      [WHERE])

例子:

考虑COMPANY表有以下记录:

ID          NAME        AGE         ADDRESS     SALARY
----------  ----------  ----------  ----------  ----------
1           Paul        32          California  20000.0
2           Allen       25          Texas       15000.0
3           Teddy       23          Norway      20000.0
4           Mark        25          Rich-Mond   65000.0
5           David       27          Texas       85000.0
6           Kim         22          South-Hall  45000.0
7           James       24          Houston     10000.0

现在,让我们检查后,子查询的SELECT语句:

sqlite> SELECT * 
     FROM COMPANY 
     WHERE ID IN (SELECT ID 
                  FROM COMPANY 
                  WHERE SALARY > 45000) ;

这将产生以下结果:

ID          NAME        AGE         ADDRESS     SALARY
----------  ----------  ----------  ----------  ----------
4           Mark        25          Rich-Mond   65000.0
5           David       27          Texas       85000.0

INSERT语句的子查询:

子查询也可以使用INSERT语句。INSERT语句中使用子查询返回的数据插入到另一个表。在子查询中所选择的数据可以被修改的任何字符,日期或数字功能。

基本语法如下:

INSERT INTO table_name [ (column1 [, column2 ]) ]
           SELECT [ *|column1 [, column2 ]
           FROM table1 [, table2 ]
           [ WHERE VALUE OPERATOR ]

例子:

考虑一个表COMPANY_BKP的具有相似结构的COMPANY 表,并可以创建,使用相同的CREATE TABLE使用COMPANY_BKP作为表名。现在复制完整的COMPANY 表成COMPANY_BKP,是语法如下:

sqlite> INSERT INTO COMPANY_BKP
     SELECT * FROM COMPANY 
     WHERE ID IN (SELECT ID 
                  FROM COMPANY) ;

UPDATE语句的子查询:

子查询可以使用UPDATE语句的结合。单个或多个表中的列的UPDATE语句中使用子查询时,都可以更新。

基本语法如下:

UPDATE table
SET column_name = new_value
[ WHERE OPERATOR [ VALUE ]
   (SELECT COLUMN_NAME
   FROM TABLE_NAME)
   [ WHERE) ]

例子:

假设我们有提供COMPANY_BKP表,这是COMPANY 表的备份。 

下面的示例更新COMPANY表中的工资的0.50倍,为所有的客户,其年龄大于或等于27:

sqlite> UPDATE COMPANY
     SET SALARY = SALARY * 0.50
     WHERE AGE IN (SELECT AGE FROM COMPANY_BKP
                   WHERE AGE >= 27 );

这将影响两行和最后COMPANY表中有下列记录:

ID          NAME        AGE         ADDRESS     SALARY
----------  ----------  ----------  ----------  ----------
1           Paul        32          California  10000.0
2           Allen       25          Texas       15000.0
3           Teddy       23          Norway      20000.0
4           Mark        25          Rich-Mond   65000.0
5           David       27          Texas       42500.0
6           Kim         22          South-Hall  45000.0
7           James       24          Houston     10000.0

DELETE语句的子查询:

该子查询可用于结合与DELETE语句等与上面提到的任何其它语句。

基本语法如下:

DELETE FROM TABLE_NAME
[ WHERE OPERATOR [ VALUE ]
   (SELECT COLUMN_NAME
   FROM TABLE_NAME)
   [ WHERE) ]

例子:

假设我们有提供COMPANY_BKP表,这是COMPANY 表的备份。

下面的示例删除记录其年龄大于或等于27的所有客户从COMPANY 表:

sqlite> DELETE FROM COMPANY
     WHERE AGE IN (SELECT AGE FROM COMPANY_BKP
                   WHERE AGE > 27 );

这将影响两行和最后COMPANY表中有下列记录:

ID          NAME        AGE         ADDRESS     SALARY
----------  ----------  ----------  ----------  ----------
2           Allen       25          Texas       15000.0
3           Teddy       23          Norway      20000.0
4           Mark        25          Rich-Mond   65000.0
5           David       27          Texas       42500.0
6           Kim         22          South-Hall  45000.0
7           James       24          Houston     10000.0

SQLite Like 子句

实例

下面一些实例演示了 带有 '%' 和 '_' 运算符的 LIKE 子句不同的地方

语句描述
WHERE SALARY LIKE '200%'查找以 200 开头的任意值
WHERE SALARY LIKE '%200%'查找任意位置包含 200 的任意值
WHERE SALARY LIKE '_00%'查找第二位和第三位为 00 的任意值
WHERE SALARY LIKE '2_%_%'查找以 2 开头,且长度至少为 3 个字符的任意值
WHERE SALARY LIKE '%2'查找以 2 结尾的任意值
WHERE SALARY LIKE '_2%3'查找第二位为 2,且以 3 结尾的任意值
WHERE SALARY LIKE '2___3'查找长度为 5 位数,且以 2 开头以 3 结尾的任意值

一.

QTableWidget继承自QTableView。QSqlTableModel能与QTableView绑定,但不能于QTableWidget绑定。

1. QSqlTableModel *model = new QSqlTableModel;  

2. model->setTable("employee");  
3. model->setEditStrategy(QSqlTableModel::OnManualSubmit);  
4. model->select();  
5. model->removeColumn(0); // don't show the ID  
6. model->setHeaderData(0, Qt::Horizontal, tr("Name"));  
7. model->setHeaderData(1, Qt::Horizontal, tr("Salary"));  
8.   
9. QTableView *view = new QTableView;  
10. view->setModel(model);  
11. view->show();  

QTableWidget与QTableView的区别

QTableWidget是QTableView的子类,主要的区别是QTableView可以使用自定义的数据模型来显示内容(也就是先要通过setModel来绑定数据源),而QTableWidget则只能使用标准的数据模型,并且其单元格数据是QTableWidgetItem的对象来实现的(也就是不需要数据源,将逐个单元格内的信息填好即可)。这主要体现在QTableView类中有setModel成员函数,而到了QTableWidget类中,该成员函数变成了私有。使用QTableWidget就离不开QTableWidgetItem。QTableWidgetItem用来表示表格中的一个单元格,正个表格都需要用逐个单元格构建起来。

​ 具体区别表格

区别点QTableViewQTableWidget
继承关系QTableWidget继承自QTableView
使用数据模型setModel可以使用setModel设置数据模型setModel是私有函数,不难使用该函数设置数据模型
显示复选框setCheckState没有函数实现复选框QTableWidgetItem类中的setCheckState(Qt::Checked);可以设置复选框
与QSqlTableModel绑定QTableView能与QSqlTableModel绑定QtableWidget不能与QSqlTableModel绑定

     

View与Model绑定注意事项

但视图与模型绑定时,模型必须使用new来创建。否则视图不能随着模型的改变而改变。

Eorror错误的写法

1. QStandardItemModel model(4,2);  
2.   
3.   
4. model.setHeaderData(0, Qt::Horizontal, tr("Label"));  
5. model.setHeaderData(1, Qt::Horizontal, tr("Quantity"));  
6.   
7.   
8. ui.tableView->setModel(&model);  
9.   
10. for (int row = 0; row < 4; ++row) {  
11.     for (int column = 0; column < 2; ++column) {  
12.         QModelIndex index = model.index(row, column, QModelIndex());  
13.         model.setData(index, QVariant((row+1) * (column+1)));  
14.     }  
15. }  
16.    
​

Right 正确的写法

1. QStandardItemModel *model;  
2.   
3. model = new QStandardItemModel(4,2);  
4. ui.tableView->setModel(model);  
5.   
6. model->setHeaderData(0, Qt::Horizontal, tr("Label"));  
7. model->setHeaderData(1, Qt::Horizontal, tr("Quantity"));  
8.   
9. for (int row = 0; row < 4; ++row) {  
10.     for (int column = 0; column < 2; ++column) {  
11.         QModelIndex index = model->index(row, column, QModelIndex());  
12.         model->setData(index, QVariant((row+1) * (column+1)));  
13.     }  
14. }  
15.    
​

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值