一、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 字段(desc或asc) ;(降序或升序)
分组: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和27
WHERE ID
NOT IN(
selectID
from AGE WHEREID > 11
ANDID < 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 n
2
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用来表示表格中的一个单元格,正个表格都需要用逐个单元格构建起来。
具体区别表格
区别点 | QTableView | QTableWidget |
---|---|---|
继承关系 | 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.