SQL 32 (金风玉露一相逢,胜却人间无数)
将employees表的所有员工的last_name和first_name拼接起来作为Name,中间以一个空格区分
(注:
采用sqlite编译时,字符串拼接为 || 符号,concat函数不被支持;
采用mysql时,支持concat函数)
CREATE TABLE employees
( emp_no
int(11) NOT NULL,birth_date
date NOT NULL,first_name
varchar(14) NOT NULL,last_name
varchar(16) NOT NULL,gender
char(1) NOT NULL,hire_date
date NOT NULL,
PRIMARY KEY (emp_no
));
思路:
属于将两列内容利用各“编译器”特定的语句,来实现列之间的合并。
解答:
(1)sqlite Version
SELECT last_name || ' ' || first_name AS Name FROM employees
*warning: *引号中间记得敲一记空格
(2)MySQL Version
SELECT CONCAT(last_name,' ',first_name) AS Name FROM employees
SQL 33 (万物皆由人的意志而创造)
创建一个actor表,包含如下列信息
列表 类型 是否为NULL 含义
actor_id smallint(5) not null 主键id
first_name varchar(45) not null 名字
last_name varchar(45) not null 姓氏
last_update date not null 日期
思路:根据SQL编译的版本来选择具体的语句
解答:sqlite Version
CREATE TABLE IF NOT EXISTS actor( actor_id smallint(5) not null , first_name varchar(45) not null, last_name varchar(45) not null, last_update date not null default(datetime('now','localtime')), primary key(actor_id) )
warning:不过实际操作时,用MySQL将题解中的几个不同的方式尝试了一下,单纯的create table actor,以及不涉及默认时间的设定这一版代码无法跑通,原因目前还不了解。
SQL 34 批量插入数据(一支穿云箭)
题目描述
题目已经先执行了如下语句:
drop table if exists actor; CREATE TABLE actor ( actor_id smallint(5) NOT NULL PRIMARY KEY, first_name varchar(45) NOT NULL, last_name varchar(45) NOT NULL, last_update DATETIME NOT NULL)
请你对于表actor批量插入如下数据(不能有2条insert语句哦!)
actor_id first_name last_name last_update 1 PENELOPE GUINESS 2006-02-15 12:34:33 2 NICK WAHLBERG 2006-02-15 12:34:33
思路:对于选择数据进行插入。需要注意的是,插入数据涉及很多列信息时,需要注意插入数据与现存表之间的顺序问题。
(1)默认插入顺序与已知表顺序已知(或者说已知表顺序,也已知待插入数据顺序情况下):
INSERT INTO actor VALUES (1, 'PENELOPE', 'GUINESS', '2006-02-15 12:34:33'), (2, 'NICK', 'WAHLBERG', '2006-02-15 12:34:33');
(2)已知表顺序和待插入顺序不一致(或者需要批量插入大规模数据,无法保证数据顺序均一致):
INSERT INTO actor(actor_id, first_name, last_name, last_update) VALUES(1,'PENELOPE','GUINESS','2006-02-15 12:34:33'), (2,'NICK','WAHLBERG','2006-02-15 12:34:33')
warning:此类语法下,actor_id 默认对应于输入数据中的“第一号位置”代表的内容,以此类推。
SQL 35 批量插入无重复数据(穿云箭+)
题目描述
题目已经先执行了如下语句:
drop table if exists actor; CREATE TABLE actor ( actor_id smallint(5) NOT NULL PRIMARY KEY, first_name varchar(45) NOT NULL, last_name varchar(45) NOT NULL, last_update DATETIME NOT NULL); insert into actor values ('3', 'WD', 'GUINESS', '2006-02-15 12:34:33');
对于表actor插入如下数据,如果数据已经存在,请忽略(不支持使用replace操作)
actor_id first_name last_name last_update '3' 'ED' 'CHASE' '2006-02-15 12:34:33'
思路:插入无重复数据,利用语法。(注意,sqlite和MySQL语法使用上存在不同,不要混淆)
解答:
(1)sqlite Version
INSERT OR IGNORE INTO actor VALUES(3,'ED','CHASE','2006-02-15 12:34:33')
(2)MySQL Version
INSERT IGNORE INTO actor VALUES(3,'ED','CHASE','2006-02-15 12:34:33')
结合《SQL 必知必会15》 插入数据
(1)INSERT 能做什么?
A、插入完整的一行;
B、插入行的一部分;
C、插入某些查询的结果;
*warning:使用INSERT语句可能需要客户端/服务器DBMS中的特定安全权限。在试图使用INSERT前,应该保证自己有足够的安全权限。
A、插入完整行
需指定:(1)待插入表名 (2)插入到新行中的值
INSERT INTO Customs VALUES('aa', 'bb', 'cc')
存储在CUSTOMS表中的每一列数据需要在VALUES子句中给出。(每一列需要提供一个值,如果为空则用NULL;各列数据需要依表列次序进行填充)
*warning:此语句高度依赖表列次序。不能经受变动,语句不安全。
Update Version
INSERT INTO Customs(V1, V2, V3) VALUES('aa', 'bb', 'cc')
此新版本与第一版工作能力完全相同,但在“指定插入表名”后括号之中给出了“每一列的具体名称”。插入行数据时,VALUES只需要将待插入列数据对应输入即可。例:V1对应aa……
因为提供了列名,VALUES必须以列名指定顺序输入数据,但是这就不一定需要按照各列在表中实际顺序进行输入——也就是表结构发生改变,输入语句仍能正常运行。
B、插入行的一部分
引用A中的第二版本,我们可以在表名后括号内指定“列”。所以——借助此语句,我们可以指给一行中“部分列”提供数值。
warning:*在表定义允许的情况下**,可以在INSERT操作中省略某些列。只是“可省略列”需要满足以下要求:
(1)该列定义允许为NULL
(2)表于定义中给出“默认值”(即如不输入数值,则取默认A)
C、插入某些查询的结果(插入多行)
INSERT INTO Customs(V1, V2, V3) SELECT V1, V2, V3 FROM Customs_old
*warning:注意两张表的“主键值”不要重复,否则后续INSERT会失败。但如果“SELECT”的表本身为“空”,那么将不会有行被插入,并不会产生错误。
SELECT 选择的列名并不重要!因为选择的第一列(无论名称一致否)对应“INSERT INTO”的第一列……(本质上是一个位置的对应关系)
(2)将A表内容复制到B表(新创建的表)
使用SELECT INTO 语句(DB2不支持)
Difference:
INSERT SELECT SELECT INTO
将A表内容插入至已存在的B表 将A表内容导出到新表B
SELECT * INTO B FROM A
此语句就是创建了新表“B”,并且将“A”表中的内容整个复制到了“B”中。(这里*作为通配符,代表将A全部内容复制到B,而如果只想选择部分列,则指定“列名”即可)
Version MySQL
CREATE TABLE B AS SELECT * FROM A
*warning:使用SELECT INTO 语句的注意事项:
(1)SELECT语句的基本选项和语句此处都可使用。(含WHERE/GROUP BY)
(2)可利用联结从多个表中插入数据
(3)但只能插入到一个表中