Chinaunix首页 | 论坛 | 博客
  • 博客访问: 104573594
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: DB2/Informix

2008-03-19 21:06:26

 
每个数据库管理系统(DBMS)都有其自己的数据处理语言(DML),但所有DML都基于一种语言SQL语言——结构化查询语言(SQL),其发音为“sequel”或“S-Q-L”。 

  目前SQL的前身是E.F.Codd博士70年代发明的。第一个实现是在76年,称为sequel。而SQL首先被采用是在IBM的System R项目中。86年10月由ANSI确定为正式的关系查询语言标准。ISO在对其修改后在90年制定为国际工业标准。 

  无论进行何种数据库学习,SQL语言都是必学内容。在我国数据库语言SQL标准(GB12991)中规定了两个数据库语言的语法与语义: 


模式定义语言(SQL-DDL),描述SQL数据库的结构与完整性的约束; 


数据操纵语言(SQL-DML),描述操作数据库的执行语句 
  在本文章中涉及以上两个中的主要部分,(为叙述方便,以下对其统称为SQL),由于SQL在嵌入C时表现略有不同,所以下面均以非嵌入时的SQL进行。另外本文章也不是SQL的入门教材,阅读者应学习并实际用SQL操作过某种数据库。 

  如果你系统学习过数据库理论,又能熟练操作INFORMIX关系数据库,甚至从事过有关数据库程序的设计,还那么作者在此恭喜你了。如果你尚未系统学习过数据库理论,并对INFORMIX数据库了解甚少,建议你先阅读有关的文档。
【主要SQL语句详解】 

CREATE DATABASE database_name [WITH LOG IN “pathname”] 


创建数据库。 

database_name:数据库名称。 

“pathname”:事务处理日志文件。 

创建一database_name.dbs目录,存取权限由GRANT设定,无日志文件就不能使用 

BEGIN WORK等事务语句(可用START DATABASE语句来改变)。 

可选定当前数据库的日志文件。 

如:select dirpath form systables where tabtype = “L”; 

例:create databse customerdb with log in “/usr/john/log/customer.log”; 



DATABASE databse-name [EXCLUSIVE] 

选择数据库。 

database_name:数据库名称。 

EXCLUSIVE:独占状态。 

存取当前目录和DBPATH中指定的目录下的数据库,事务中处理过程中不要使用此语句。 

例:dtabase customerdb; 



CLOSE DATABASE 


关闭当前数据库。 

database_name:数据库名称。 

此语句之后,只有下列语句合法: 

CREATE DATABASE; DATABASE; DROP DATABSE; ROLLFORWARD DATABASE; 

删除数据库前必须使用此语句。 

例:close database; 



DROP DATABASE database_name 


删除指定数据库。 

database_name:数据库名称。 用户是DBA或所有表的拥有者;删除所有文件,但不包括数据库目录;不允许删除当前数据库(须先关闭当前数据库);事务中处理过程中不能使用此语句,通过ROLLBACK WORK 也不可将数据库恢复。 

例:drop databse customerdb; 



CREATE [TEMP] TABLE table-name (column_name datatype [NOT NULL], …) 


[IN “pathname”] 

创建表或临时表。 

table-name :表名称。 

column_name:字段名称。 

data-type:字段数据类型。 

path-name:指定表的存放位置 

TEMP用于指定建立临时表;表名要唯一,字段要唯一;有CONNECT权限的用户可建立临时表;创建的表缺省允许CONNECT用户存取,但不可以ALTER。 

例:create table user 

( c0 serial not null, c1 char (10), 

c2 char(2), 

c3 smallint, 

c4 decimal(6,3), 

c5 date 

) in “usr/john/customer.dbs/user; 



ALTER TABLE 


ALTER TABLE table-name 

{ADD (newcol_name newcol_type [BEFORE oldcol_name], …) | DROP (oldcol_name, …) 

| MODIFY (oldcol_name newcol_type [NOT NULL], … )}, … 

修改表结构。 

table-name:表名称。 

newcol_name:新字段名称 

newcol_type:新字段类型 

oldcol_name:老字段名称 

可以使用单个或多个ADD子句、DROP子句、MODIFY子句,但某个字句失败,操作即中止;原字段是NULL,不允许MODIFY为NOT NULL,除非所有NULL字段中均非空,反之可以;ALTER使用者是表的拥有者或拥有DBA权限,或被授权;事务中处理过程中不要使用此语句。 

例:alter table user 

add ( c6 char(20) before c5); 



RENAME TABLE oldname TO newname 


修改表名。 

oldname:原名称。 

newname:新名称。 

RENAME使用者是表的拥有者或拥有DBA权限,或被授权;事务中处理过程中不要使用此语句。 例:rename user to bbb; 



DROP TABLE table-name 


删除表。 

table-name:表名称。 

删除表意味着删除其中所有数据、各字段上的索引及对表的赋权、视图等;用户不能删除任何系统目录表;语句使用者是表拥有者或拥有DBA权限,事务中处理过程中不要使用此语句。 



RENAME COLUMN table.oldcolumn, TO newcolumn 


修改字段名。 

table.oldcolumn:表名及原字段名称 

newcolumn:新字段名称。 

语句使用者是表的拥有者或拥有DBA权限或有ALTER权限的用户,事务中处理过程中不要使用此语句。 

例:rename column user.c6 to c7; 



CREATE VIEW view-name column-list 


CREATE VIEW view-name column-list AS select_statement [WITH CHECK OPTION] 

创建视图。 

view-name:视图名称。 

column-list:字段列表。 

select_statement:SELECT语句。 

以下语句不使用视图:ALTER TABLE,DROP INDEX,ALTER INDEX,LOCK TABLE,CREATE INDEX, RENAME TABLE;视图将延用基表的字段名,对表达式等虚字段和多表间字段重名必须指明标识其字段名;若对视图中某些字段命名,则所有字段都必须命名;视图中数据类型延用基表中的数据类型,虚字段起诀于表达式;不能使用ORDER BY和UNION子句;对视图中所有的字段要有SELECT权限;事务中处理过程中使用此语句,即使事务回滚,视图也将建立,不能恢复。 

例:create view v_user as select * from user where c1 = “B1”; 



DROP VIEW view-name 


删除视图。 

view-name:视图名称。 

用户可删除自己建立的视图;视图的后代视图也被删除;事务中处理中不要使用此语句。 

例:drop view v_user; 



CREATE INDEX 


CREATE [UNIQUE/DISTINCT] [CLUSTER] INDEX index_name ON table_name 

([column_name ASC/DESC],…) 

创建索引。 

index_name:索引名称。 

table_name:表名称。 

column_name:字段名称。 

UNIQUE/DISTINCT:唯一索引。 

CLUSTER:使表的物理存放顺序按索引排列。 

ASC/DESC:升序或降序,缺省升序。 

语句执行时,将表的状态置为EXCLUSIVE;复合索引最多包含8个字段,所有字段长度和不得大于120字节;事务中处理过程中使用此语句,即使事务回滚,索引将建立,不能恢复。 

例:create cluster index ix_user on user(c5); 



ALTER INDEX index-name TO [NOT] CLUSTER 


修改索引性质。 

index-name:索引名称。 

TO [NOT] CLUSTER:去掉或加上CLUSTER属性。 

语句执行时,将表的状态置为EXCLUSIVE;事务中处理过程中使用此语句,即使事务回滚,索引性质将改变,不能恢复。 

例:alter index ix_user to not cluster; 



DROP INDEX index-name 


删除索引。 

index-name:索引名称。 

语句使用者是索引的拥有者或拥有DBA权限,事务中处理过程中不要使用此语句,否则事务无法恢复。 

例:drop index ix_user; 



CREATE SYNONYM synonym FOR table-name 


创建同义名。 

synonym:同义名 

table-name:表名称 

数据库的创建者可以使用同义名;没有赋予同义名权限的用户不能使用同义名;同义名不能和表名相同;事务中处理过程中不要使用此语句。 

例:create synonym user_alias for user; 



DROP SYNONYM synonym 


删除同义名。 

synonym:同义名 

可以删除自己建立的同义名;事务中处理过程中不要使用此语句,否则无法恢复。 

例:drop synonym user_alias; 



UPDATE STATISTICS [FOR TABLE table-name] 


更新数据库的统计数字。 

table-name:表名称 

此语句仅作用于当前数据库;可提高查询效率;只有执行此语句,才改变统计数据。 

例:update statistics for table user;
GRANT {DBA|RESOURCE|CONNECT} TO {PUBLIC|user-list} 
授权命令。 

PUBLIC|user-list:全部或指定的用户。 

三种权限居且仅居其一,事务处理过程中不要执行GRANT语句。 

例:grant resource to pulbic; 

GRANT tab-privilege ON table-name TO {PUBLIC|user-list} [WITH GRANT OPTION] 


授表级权限。 

tab-privilege:表级权限。 

table-name:表名称。 

PUBLIC|user-list:全部或指定的用户。 

[WITH GRANT OPTION]:表示被授权用户有否权限进行二次授权。 

用户可以在自己建立表达式或被[WITH GRANT OPTION]准许的表中进行赋权;限定越多的权限优先级越高。 

例:grant update(c1,c6) on user to dick with grant option; 


附(INFORMIX的权限) 

(1) 数据库的权限(控制对数据库的访问以及数据库中表的创建和删除) 


DBA权限:全部权利,修改系统表,建立和删除表与索引、增加和恢复表数据,以及授予其他用户数据库权限等; 

RESOURCE权限:允许对数据库表中的数据进行存取,建立永久性表以及索引。 

CONNECT权限:只允许对数据库表中的数据进行存取,建立和删除视图与临时表。 

(2)表级权限(对表的建立、修改、检索和更新等权限) 


ALTER:更改权限 

DELETE:删除权限 

INDEX:索引权限 

INSERT:插入权限 

SELECT [(cols)]:指定字段或所有字段上的查询权限,不指明字段缺省为所有字段。 

UPDATE [(cols)] :指定字段或所有字段上的更新权限,不指明字段缺省为所有字段。 

ALL [PRIVILEGES]:以上所有表级权限 



REVOKE {DBA|RESOURCE|CONNECT} FROM {PUBLIC|user-list} 

收权命令。 

PUBLIC|user-list:全部或指定的用户。 

三种权限居且仅居其一,事务处理过程中不要执行GRANT语句。 

例:revoke resource from john; 

REVOKE tab-privilege ON table-name FROM {PUBLIC|user-list} 


收表级权限。 

tab-privilege:表级权限。 

table-name:表名称。 

PUBLIC|user-list:全部或指定的用户。 

[WITH GRANT OPTION]:表示被授权用户有否权限进行二次授权。 

用户只能取消由其本人赋予其他用户的表级存取权限;不能取消自己的权限,对SELECT和UPDATE作取消时,将取消所有表中字段的SELECT 和UPDATE权限。 

例;revoke update on user from dick; 



LOCK TABLE table-name IN {SHARE|EXCLUSIVE} MODE 

记录级加锁和表级加锁或文件加锁。 

table-name:表名称。 

SHARE:允许读表中数据,但不允许作任何修改 

EXCLUSIVE:禁止其他任何形式访问表 

每次只能对表琐定一次;事务处理过程中,BEGIN WORK后立即执行LOCK TABLE以取代记录级加锁,COMMIT WORK和ROLLBACK WORK语句取消所有对表的加锁;若没有事务处理,锁将保持到用户退出或执行UNLOCK为止。 

例:lock table user in exclusive mode; 



UNLOCK TABLE table-name 

取消记录级加锁和表级加锁或文件加锁。 

table-name:表名称。 

例:unlock user; 



SET LOCK MODE TO [NOT] WAIT 

改变锁定状态。 

TO [NOT]:等待解锁,有可能被死锁或不等待并提示错误信息,表示此记录被锁,缺省值。 

访问一个EXCLUSIVE状态下的记录,将返回一个错误。 



START DATABSE db_name [WITH LOG IN “pathname”] 

启动事务处理。 

“pathname”:事务处理日志文件。 

执行该语句前,需要先关闭当前数据库。 

例;clost database; 

start databse customer with log in “/usr/john/log/customer.log”; 



BEGIN WORK 

开始事务。例:begin work; 



COMMIT WORK 

提交(正常结束)事务。例:commit work; 



ROLLBACK WORK 

回滚(非正常结束)事务。例:rollback work; 



SELECT 

SELECT select_list FROM tab_name|view_name 

WHERE condition 

GROUP BY column_name 

HAVING condition 

ORDER BY column_list 

INTO TEMP table_name 

查询语句。 

select_list:选择表或* 

tab_name:表名称 

view_name:视图名称。 

condition:查询条件,可使用BETWEEN、IN、LIKE、IS NULL、LIKE、MATCHES、NOT、 

AND、OR、=、!=或<>、>、 >= 、<=、<、ALL、ANY、SOME 

column_name:分组字段名称 

condition:群聚条件 

column_list:排序字段列表,缺省ASC,可指定DSC;排序时,NULL值小于非零值。 

table_name:临时表名称 

例:略 

附(常用函数) 

(1)集合函数: 

count(*)、 

sum(数据项/表达式)、avg(数据项/表达式)、max(数据项/表达式)、min(数据项/表达式) 

count(distinct 数据项/表达式)、sum(distinct数据项/表达式)、avg(distinct数据项/表达式) 

(2)代数函数和三角函数 

HEX(数据项/表达式)、ROUND(数据项/表达式)、TRUNC(数据项/表达式)、 

TAN(数据项/表达式)、ABS(数据项/表达式)、MOD(被除数,除数) 

(3)统计函数 

标准差,stdev()、方差,variance()、范围,rang() 

(4)时间函数 

DAY(日期/时间表达式):返回数字型 

MONTH(日期/时间表达式):返回整数 

WEEKDAY(日期/时间表达式):0��6,0星期天,1星期一;返回整数 

YEAR(日期/时间表达式)、返回整数 

DATE(非日期表达式):返回日期型 

EXTEND(日期/时间表达式,[第一个至最后一个]):返回指定的整数 

MDY(月,日,年):返回日期型 

CURRENT:返回日期型 

(5)时间函数 

ROUND(),四舍五入。如:ROUND(10.95,position)position进行四舍五入的前一位置 

TRUNC(),截取。如:TRUNC(10.95,0)position截取的位置 

INFORMIX临时表在下列情况下自动取消: 

A.退出数据库访问工具(如DBACCESS) 

B.SQL通话结束(DISCONNECT) 

C.发出取消表语句 

D.退出程序时 


INSERT 
INSERT INTO view_name|table_name [(column_list)] valueS (value_list) 

或 INSERT INTO view_name|table_name [(column_list)] select_statement 

插入数据 

view_name|table_name:视图名或表名称 

column_list:数据项列表。 

value_list:值列表  
select_statement:查询语句。 

例:略 


DELETE FROM view_name|table_name WHERE search-conditions 
删除语句。 

view_name|table_name:视图名或表名称 

search-conditions;删除条件 

例:略 


UPDATE 
UPDATE view_name|table_name SET column_1 = value_1ist WHERE search_conditions 

或UPDATE view_name|table_name SET column_1|* = value_1ist WHERE search_conditions 

更新数据语句。 

view_name|table_name:表名称或视图表名称 

value_1ist:字段值 

search_conditions:更新数据的条件 

例:略 


CHECK TABLE table-name 
检查索引语句。 

语句使用者是表的拥有者或拥有DBA权限;不能对systable使用此语句。 

例:略 


REPAIR TABLE table-name 
修复索引。 

语句使用者是表的拥有者或拥有DBA权限;不能对systable使用此语句。 

例:略 


LOAD FROM “file-name” INSERT INTO table_name [(column_name[,…])] 
将文本数据栽入表中。 

例:load form “aa.txt” insert into user; 


UNLOAD TO “pathname” 
将表中数据卸为文本。 

例:unload to “aa.txt” select * from user; 


INFO 
系统信息查询。 

INFO TABLES:得到当前数据库上表的名字。 

INFO columns FOR table_name:指定表上的字段信息。 

INFO INDEXES FOR table_name:指定表上的索引信息。 

INFO [ACCESS|PRIVILEGES] FOR table_name:指定表上的存取权限。 

INFO STATUS FOR table_name:指定表的状态信息。 


例: info tables;
1.select 语句中使用sort,或join 

如果你有排序和连接操作,你可以先select数据到一个临时表中,然后再对临时表进行处理。因为临时表是建立在内存中,所以比建立在磁盘上表操作要快的多。 

如: 

SELECT time_records.*, case_name 

FROM time_records, OUTER cases 

WHERE time_records.client = "AA1000" 

AND time_records.case_no = cases.case_no 

ORDER BY time_records.case_no 


这个语句返回34个经过排序的记录,花费了5分钟42秒。而: 

SELECT time_records.*, case_name 

FROM time_records, OUTER cases 

WHERE time_records.client = "AA1000" 

AND time_records.case_no = cases.case_no 

INTO temp foo; 

SELECT * from foo ORDER BY case_no 

返回34条记录,只花费了59秒。 


2.使用not in 或者not exists 语句 

下面的语句看上去没有任何问题,但是可能执行的非常慢: 

SELECT code FROM table1 

WHERE code NOT IN ( SELECT code FROM table2 ) 


如果使用下面的方法: 

SELECT code, 0 flag 

FROM table1 

INTO TEMP tflag; 

然后: 

UPDATE tflag SET flag = 1 

WHERE code IN ( SELECT code 

FROM table2 

WHERE tflag.code = table2.code ); 

然后: 

SELECT * FROM 

tflag 

WHERE flag = 0; 

看上去也许要花费更长的时间,但是你会发现不是这样。 

事实上这种方式效率更快。有可能第一种方法也会很快,那是在对相关的每个字段都建立了索引的情况下,但是那显然不是一个好的注意。 


3.避免使用过多的“or" 

如果有可能的话,尽量避免过多地使用or: 

WHERE a = "B" OR a = "C" 

要比 

WHERE a IN ("B","C"

慢。 

有时甚至UNION会比OR要快。 


4.使用索引。 

在所有的join和order by 的字段上建立索引。 
在where中的大多数字段建立索引。 
WHERE datecol >= "this/date" AND datecol <= "that/date" 
要比 
WHERE datecol BETWEEN "this/date" AND "that/date" 慢 


如何在shell脚本中使用一个sql查询的结果? 

以下的是一个运行在sh/ksh下面的脚本。在online中,如果你想要更新一个有许多表的数据库的统计信息。这个脚本不太好。因为这个脚本只能单个处理数据库中的表,而不能同时处理大量的表。 

例子: 

# update_em 

# Run UPDATE STATISTICS on a table by table basis 



DATABASE=$1 

if [ -z "$DATABASE" ] 

then 

echo "usage: update_em dbname" >&2 

exit 1 

fi 

isql $DATABASE - < dev/null | isql $DATABASE - 

output to pipe "cat" without headings 

select "update statistics for table ", tabname, ";" 

from systables where tabid >= 100 order by tabname; 

EOF 

exit 0 


也许你已经注意到exit的返回值对不同的isql不是都相同,因此这样作不是很可靠,代替通过$?来检查返回值的更好的主意是将标准错误重定向到一个文件中,然后在这个文件中grep “error"。例如: 

# Generate the data 

isql -qr <stage.rep 2>$stage.err 

database $database; 

select ... 



# Check for errors 

if grep -i "error" $stage.err >/dev/null 

then 

...error_handler... 

fi 


为什么不能对一个计算产生的字段创建视图? 

问题:为什么我不能创建视图: 

CREATE VIEW tst AS 

SELECT ship_charge - totval cout 

FROM orders WHERE ship_charge > 0; 

回答:你应该这样写: 

CREATE VIEW tst (cout) AS 

SELECT ship_charge - totval 

FROM orders WHERE ship_charge > 0; 


如何只select 出数据库中的部分数据(例如10%)。 

问题:如果你想要得到一个select 语句正常返回的数据的一部分,例如: 

SELECT firstname, lastname, city, state 

FROM bigdatabase 

WHERE state = "TX" 

回答: 

有一个方法可以返回一个近似值,只需要在where后加上: 

AND rowid=(trunc(rowid/x)*x) 

其中的x代表你想要返回的总的记录的1/x。需要说明的是,这种方法只能返回一个近似的值,并且表中的数据在物理上分布的连续性。 


如何创建一个表结构和永久表完全一致的临时表。 例如:CREATE TEMP TABLE mytemp (prodno LIKE product.prodno 

desc LIKE product.desc) 

你可以使用如下的语句: 

SELECT prodno, desc FROM product 

WHERE ROWID = -1 

INSERT INTO TEMP mytemp
如何更改serial类型下一次插入操作产生的值? 

我们知道serial类型的字段是系统自动增加的整数字段,那么怎样能控制下一个serial类型字段的值。 

想要下一个插入的serial类型的值比默认值大,可以用: 

ALTER TABLE tabname MODIFY( ser_col_name SERIAL([new_start_number]) 

想要下一个插入的serial类型的值比默认的值要小,首先需要将serial类型重新置为1: 

INSERT INTO table (serial_column) valueS (2147483647); 

INSERT INTO table (serial_column) valueS (0); -- 重新从1开始! 

....然后执行ALTER TABLE(就像上面的做法一样)。 


如何在发生错误的时候终止sql脚本的执行? 

如果你创建了一个sql脚本,并且在UNIX命令行中使用以下的方式来执行这个脚本: 

$ dbaccess  <脚本文件名> 

这时,脚本中的所有的sql语句都会被执行,即使其中的一个sql语句发生了错误。例如,如果你脚本中为如下的语句: 

BEGIN WORK; 

INSERT INTO history 

SELECT * 

FROM current 

WHERE month = 11; 

DELETE FROM current 

WHERE month = 11; 

COMMIT WORK; 

如果INSERT语句失败了,DELETE语句仍旧会继续执行。直到commit work。这样的后果可能会很严重。你可以通过设置一个环境变量来防止这种情况的发生。 

DBACCNOIGN=1 


如何设置decimal字段运算结果的精度? 

假定你使用dbaccess或者isql,设置环境变量DBFLTMASK=6 就可以设置为小数点后面6位,比如: 

CREATE TEMP TABLE t 

( col_a DECIMAL(8,4) NOT NULL, 

col_b DECIMAL(8,4) NOT NULL, 

col_c DECIMAL(8,4) NOT NULL 

); 

INSERT INTO t valueS(1.2345, 3.4567, 5.6789); 

SELECT (col_a + col_b) / col_c AS value FROM t; 

value 0.826075 

如果DBFLTMASK=7 

value 0.8260755 


为什么我们有时会遇到sysprocplan表被锁的提示? 

sysprocplan表是sysmaster库中的一个表,其中记录存储过程经过优化的查询计划。每当查询树中的数据库对象有任何结构上的变化,这个查询计划就会自动更新。如果对查询树中存在的任何表有update statistics操作,也会自动更新查询计划。在查询计划更新的时候,会对sysporcplan表中的相关记录加锁。 

注意:每次你对一个表更新统计的时候,也同时会更新于这个表相关的存储过程,即UPDATE STATISTICS FOR PROCEDURE 。 

你可以作的另外一件事情就是:在存储过程中使用SET OPTIMIZATION LOW,这会让优化器在存储过程运行的时候不会试图去重新优化它。否则存储过程通常都会被重新优化一次。 




如何删除掉表中重复的记录? 

假设“keycol”字段的值唯一,而且没有对表进行分片,并且没有其它的人正在删除"sometable"中的记录,你可以执行如下的SQL: 

delete from sometable as a 

where rowid <> (select min(rowid) from sometable where keycol = a.keycol) 

如果这个表使用表分片,rowid不存在,你还可以用如下的方法: 

BEGIN WORK; 

SELECT DISTINCT * FROM Table INTO TEMP Temp1; 

DELETE FROM Table WHERE 1 = 1; 

INSERT INTO Table SELECT * FROM Temp1; 

COMMIT WORK; 

对于规模较小或中等的表,并且你有足够的存储空间来存储整个的临时表的时候,这种方法通常十分有效。 


如何加快SELECT COUNT(DISTINCT)的速度。 

通常“SELECT COUNT(DISTINCT)”这样的操作要花费比较长的时间,如果你这样作: 

SELECT UNIQUE xxx INTO TEMP XXX " 然后再"SELECT COUNT(*) FROM TEMP XXX"
NULL值的使用 

RDSQL中字段缺省值为空;并且对数值型的0和空值,以及字符型的空白和空值区别对待。 
数值表达式中某个变为空,则整个表达式值为空; 
聚合函数中,对空值忽略不计,若全部为空值,除COUNT(*)返回0外,其余返回空值。 
布尔表达式中,结果可能为“未知”(见下表)。如TRUE AND NULL 结果为 “未知”,对“未知”结果在RDSQL中看作不符合查询条件。 

and 



  or 



  not 
  




  T 



  T 






  F 



  F 






  ? 



  ? 



结合上表,分析下列子句 ,其中n1=20;n2为空;n3=30。结果如右。 

where n1*n2 < 1000 and n3 = 30; 结果:不符合查询条件 
where n1*n2 < 1000 or n3 = 30; 结果:符合查询条件 

ORDER BY子句中的空值,每一个空值为一组。 
INSERT或UPDATE时,可使用关键字NULL/null表示空值。 
字段是否可以为空,由CREATE TABLE语句中是否有NOT NULL指定或由ALTER修改。 

Q:select count(*) from t1和select count(c1) from t1是否一样? 



字符查找,主要使用LIKE和MATCHES。 

LIKE 
MATCHES 
意义 



匹配0或多个字符 



匹配一个字符 



转义字符 

无 
[] 
选择匹配 


例:matches ‘*Sp’;匹配以任何字符开始,以Sp结束的字段值 
matches ‘?l*’; 匹配第一个字符任意,第二个字符为l,其余字符任意的字段值 
matches ‘[A-N]*’; 匹配以A到N的字符开始,其余字符任意的字段值 
matches ‘*[sS]*’; 匹配含有s或S的字段值,扩展以下可用于case insensitive查询 
like ‘%\%%’; 匹配含有%的字段值 


用SQL语句求表一中的关于name有多少不同的num,结果如表二。 
表一:                     表二: 
id   name   num              name     count1 
1    AA    1               CC       2 
2    AA    2               BB       2 
3    AA    3               AA       3 
4    AA    1 
5    AA    2 
6    BB    4 
7    BB    5 
8    BB    4 
9    BB    5 
10   CC    6 
11   CC    6 
12   CC    7 

SQL语句如下: 

create table t1 

id smallint, 
name char(10), 
num smallint 
); 

insert into t1 values(1,'AA',1); 
insert into t1 values(2,'AA',2); 
insert into t1 values(3,'AA',3); 
insert into t1 values(4,'AA',1); 
insert into t1 values(5,'AA',2); 
insert into t1 values(6,'BB',4); 
insert into t1 values(7,'BB',5); 
insert into t1 values(8,'BB',4); 
insert into t1 values(9,'BB',5); 
insert into t1 values(10,'CC',6); 
insert into t1 values(11,'CC',6); 
insert into t1 values(12,'CC',7); 


A:select name ,count(distinct num) from t1 group by name; 


4)使用旋转矩阵,将表一中关于id在不同月份的费用,由纵向变为横向。 

其中表一对一个id某个月份的记录数可能>1。表一: 
id   d1  fee费用(分) 
1 2000-01-24 100 
1 2000-04-24 100 
2 2000-02-24 200 
2 2000-06-24 200 
3 2000-04-24 400 
4 2000-04-24 400 
5 2000-05-24 500 
6 2000-06-24 600 
7 2000-09-24 900 
8 2000-11-24 1100 

表二: 
id 1月份费用 2月份费用 …… … … 12月份费用 
1  100 0  0  100  0  0  0  0  0  0  0   0 
2  0  200 0  0   0  200 0  0  0  0  0   0 
3  0  0  0  400  0  0  0  0  0  0  0   0 
4  0  0  0  400  0  0  0  0  0  0  0   0 
5  0  0  0  0   500 0  0  0  0  0  0   0 
6  0  0  0  0   0  600 0  0  0  0  0   0 
7  0  0  0  0   0  0  0  0  900 0  0   0 
8  0  0  0  0   0  0  0  0  0  0  1100  0 


SQL语句: 
create table t3 

id smallint, 
d1 datetime year to day, 
fee int 
); 

insert into t3 values(1,"2000-01-24", 100); 
insert into t3 values(1,"2000-04-24", 100); 
insert into t3 values(2,"2000-02-24", 200); 
insert into t3 values(2,"2000-06-24", 200); 
insert into t3 values(3,"2000-04-24", 400); 
insert into t3 values(4,"2000-04-24", 400); 
insert into t3 values(5,"2000-05-24", 500); 
insert into t3 values(6,"2000-06-24", 600); 
insert into t3 values(7,"2000-09-24", 900); 
insert into t3 values(8,"2000-11-24", 1100);  

create table t4 –旋转矩阵 

m_code smallint, 
y1 smallint, 
y2 smallint, 
y3 smallint, 
y4 smallint, 
y5 smallint, 
y6 smallint, 
y7 smallint, 
y8 smallint, 
y9 smallint, 
y10 smallint, 
y11 smallint, 
y12 smallint 
); 

insert into t4 values(1, 1,0,0,0,0,0,0,0,0,0,0,0); 
insert into t4 values(2, 0,1,0,0,0,0,0,0,0,0,0,0); 
insert into t4 values(3, 0,0,1,0,0,0,0,0,0,0,0,0); 
insert into t4 values(4, 0,0,0,1,0,0,0,0,0,0,0,0); 
insert into t4 values(5, 0,0,0,0,1,0,0,0,0,0,0,0); 
insert into t4 values(6, 0,0,0,0,0,1,0,0,0,0,0,0); 
insert into t4 values(7, 0,0,0,0,0,0,1,0,0,0,0,0); 
insert into t4 values(8, 0,0,0,0,0,0,0,1,0,0,0,0); 
insert into t4 values(9, 0,0,0,0,0,0,0,0,1,0,0,0); 
insert into t4 values(10,0,0,0,0,0,0,0,0,0,1,0,0); 
insert into t4 values(11,0,0,0,0,0,0,0,0,0,0,1,0); 
insert into t4 values(12,0,0,0,0,0,0,0,0,0,0,0,1); 


--方法一 
select id,month(d1) month,sum(fee) fei from t3 group by 1,2 into temp aa; 
select id, 
sum(y1*fei) y1,sum(y2*fei) y2,sum(y3*fei) y3,sum(y4*fei) y4, 
sum(y5*fei) y5,sum(y6*fei) y6,sum(y7*fei) y7,sum(y8*fei) y8, 
sum(y9*fei) y9,sum(y10*fei) y10,sum(y11*fei) y11,sum(y12*fei) y12 
from aa, t4 where aa.month = t4.m_code 
group by id order by id 

--方法二 
select id, 
sum(y1*fee) y1,sum(y2*fee) y2,sum(y3*fee) y3,sum(y4*fee) y4, 
sum(y5*fee) y5,sum(y6*fee) y6,sum(y7*fee) y7,sum(y8*fee) y8, 
sum(y9*fee) y9,sum(y10*fee) y10,sum(y11*fee) y11,sum(y12*fee) y12 
from t3, t4 where month(d1) = t4.m_code 
group by id order by id 


方法一和方法二的结果一样,但有所区别: 
方法一中是先对id某个月的钱进行累加,然后进行旋转; 
方法二中在表一对一个id某个月份的记录数可能>1的情况时,先对每条记录进行旋转,然后在累加求和。
阅读(778) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~