[ WITH ENCRYPTION ]
{
{
} ] { [ INSERT ] [ , ] [ UPDATE ] }
[ NOT FOR REPLICATION ]
[ { IF UPDATE ( column )
[ ...n ]
bitwise_operator
} comparison_operator
sql_statement [ ...n ]
}
}
trigger_name
是触发器的名U。触发器名称必须W合标识W规则,q且在数据库中必d一。可以选择是否指定触发器所有者名U?/p>
Table | view
是在其上执行触发器的表或视图Q有时称发器表或触发器视图。可以选择是否指定表或视图的所有者名U?/p>
WITH ENCRYPTION
加密 syscomments 表中包含 CREATE TRIGGER 语句文本的条目。?WITH ENCRYPTION 可防止将触发器作?SQL Server 复制的一部分发布?/p>
AFTER
指定触发器只有在触发 SQL 语句中指定的所有操作都已成功执行后才激发。所有的引用U联操作和约束检查也必须成功完成后,才能执行此触发器?/p>
如果仅指?FOR 关键字,?AFTER 是默认设|?/p>
不能在视图上定义 AFTER 触发器?/p>
INSTEAD OF
指定执行触发器而不是执行触?SQL 语句Q从而替代触发语句的操作?/p>
在表或视图上Q每?INSERT、UPDATE ?DELETE 语句最多可以定义一?INSTEAD OF 触发器。然而,可以在每个具?INSTEAD OF 触发器的视图上定义视图?/p>
INSTEAD OF 触发器不能在 WITH CHECK OPTION 的可更新视图上定义。如果向指定?WITH CHECK OPTION 选项的可更新视图d INSTEAD OF 触发器,SQL Server 生一个错误。用户必ȝ ALTER VIEW 删除该选项后才能定?INSTEAD OF 触发器?/p>
{ [DELETE] [,] [INSERT] [,] [UPDATE] }
是指定在表或视图上执行哪些数据修改语句时激z触发器的关键字。必至指定一个选项。在触发器定义中允许使用以Q意顺序组合的q些关键字。如果指定的选项多于一个,需用逗号分隔q些选项?/p>
对于 INSTEAD OF 触发器,不允许在h ON DELETE U联操作引用关系的表上?DELETE 选项。同P也不允许在具?ON UPDATE U联操作引用关系的表上?UPDATE 选项?/p>
WITH APPEND
指定应该d现有cd的其它触发器。只有当兼容U别?65 或更低时Q才需要用该可选子句。如果兼容别是 70 或更高,则不必?WITH APPEND 子句d现有cd的其它触发器Q这是兼容别设|ؓ 70 或更高的 CREATE TRIGGER 的默认行为)。有x多信息,请参?strong> sp_dbcmptlevel?/p>
WITH APPEND 不能?INSTEAD OF 触发器一起用,或者,如果昑ּ声明 AFTER 触发器,也不能用该子句。只有当Z向后兼容而指?FOR Ӟ没有 INSTEAD OF ?AFTERQ,才能使用 WITH APPEND。以后的版本不支持 WITH APPEND ?FORQ将被解释ؓ AFTERQ?/p>
NOT FOR REPLICATION
表示当复制进E更改触发器所涉及的表Ӟ不应执行该触发器?/p>
AS
是触发器要执行的操作?/p>
sql_statement
是触发器的条件和操作。触发器条g指定其它准则Q以定 DELETE、INSERT ?UPDATE 语句是否D执行触发器操作?/p>
当尝?DELETE、INSERT ?UPDATE 操作ӞTransact-SQL语句中指定的触发器操作将生效?/p>
触发器可以包含Q意数量和U类?Transact-SQL 语句。触发器旨在Ҏ(gu)数据修改语句查或更改数据Q它不应数据返回给用户。触发器中的 Transact-SQL 语句常常包含控制语a。CREATE TRIGGER 语句中用几个特D的表:
SELECT *
FROM deleted
当兼容别是 80 或更高时QSQL Server 允许在表或视图上通过 INSTEAD OF 触发器更?text?strong>ntext ?image 列?/p>
n
是表C发器中可以包含多?Transact-SQL 语句的占位符。对?IF UPDATE (column) 语句Q可以通过重复 UPDATE (column) 子句包含多列?/p>
IF UPDATE (column)
试在指定的列上q行?INSERT ?UPDATE 操作Q不能用?DELETE 操作。可以指定多列。因为在 ON 子句中指定了表名Q所以在 IF UPDATE 子句中的列名前不要包含表名。若要测试在多个列上q行?INSERT ?UPDATE 操作Q请在第一个操作后指定单独?UPDATE(column) 子句。在 INSERT 操作?IF UPDATE 返?TRUE |因ؓq些列插入了昑ּ值或隐?(NULL) 倹{?/p>
说明 IF UPDATE (column) 子句的功能等同于 IF、IF...ELSE ?WHILE 语句Qƈ且可以?BEGIN...END 语句块。有x多信息,请参?a >控制语a?
可以在触发器M中的L位置使用 UPDATE (column)?/p>
column
是要试 INSERT ?UPDATE 操作的列名。该列可以是 SQL Server 支持的Q何数据类型。但是,计算列不能用于该环境中。有x多信息,请参?a >数据cd?
IF (COLUMNS_UPDATED())
试是否插入或更C提及的列Q仅用于 INSERT ?UPDATE 触发器中。COLUMNS_UPDATED q回 varbinary 位模式,表示插入或更C表中的哪些列?/p>
COLUMNS_UPDATED 函数以从左到右的序q回位,最左边的ؓ最不重要的位。最左边的位表示表中的第一列;向右的下一位表C第二列Q依此类推。如果在表上创徏的触发器包含 8 列以上,?COLUMNS_UPDATED q回多个字节Q最左边的ؓ最不重要的字节。在 INSERT 操作?COLUMNS_UPDATED 对所有列q回 TRUE |因ؓq些列插入了昑ּ值或隐?(NULL) 倹{?/p>
可以在触发器M中的L位置使用 COLUMNS_UPDATED?/p>
bitwise_operator
是用于比较运的位运符?/p>
updated_bitmask
是整型位掩码Q表C实际更新或插入的列。例如,?t1 包含?C1?strong>C2?strong>C3?strong>C4 ?C5。假定表 t1 上有 UPDATE 触发器,若要查列 C2、C3 ?C4 是否都有更新Q指定?14Q若要检查是否只有列 C2 有更斎ͼ指定?2?/p>
comparison_operator
是比较运符。用等?(=) ?updated_bitmask 中指定的所有列是否都实际进行了更新。用大于号 (>) ?updated_bitmask 中指定的M列或某些列是否已更新?/p>
column_bitmask
是要查的列的整型位掩码,用来查是否已更新或插入了q些列?
触发器常常用于强制业务规则和数据完整性。SQL Server 通过表创句(ALTER TABLE ?CREATE TABLEQ提供声明引用完整?(DRI)Q但?DRI 不提供数据库间的引用完整性。若要强制引用完整性(有关表的主键和外键之间关pȝ规则Q,请用主键和外键U束QALTER TABLE ?CREATE TABLE ?PRIMARY KEY ?FOREIGN KEY 关键字)。如果触发器表存在约束,则在 INSTEAD OF 触发器执行之后和 AFTER 触发器执行之前检查这些约束。如果违反了U束Q则回滚 INSTEAD OF 触发器操作且不执行(Ȁ发)AFTER 触发器?/p>
可用 sp_settriggerorder 指定表上W一个和最后一个执行的 AFTER 触发器。在表上只能为每?INSERT、UPDATE ?DELETE 操作指定一个第一个执行和一个最后一个执行的 AFTER 触发器。如果同一表上q有其它 AFTER 触发器,则这些触发器以随机序执行?/p>
如果 ALTER TRIGGER 语句更改了第一个或最后一个触发器Q则除d修改触发器上讄的第一个或最后一个特性,而且必须?sp_settriggerorder 重置排序倹{?/p>
只有当触?SQL 语句Q包括所有与更新或删除的对象兌的引用联操作和U束查)成功执行后,AFTER 触发器才会执行。AFTER 触发器检查触发语句的q行效果Q以及所有由触发语句引v?UPDATE ?DELETE 引用U联操作的效果?/p>
CREATE TRIGGER 必须是批处理中的W一条语句,q且只能应用C个表中?
触发器只能在当前的数据库中创建,不过触发器可以引用当前数据库的外部对象?
如果指定触发器所有者名UC限定触发器,请以相同的方式限定表名?
在同一?CREATE TRIGGER 语句中,可以为多U用h作(?INSERT ?UPDATEQ定义相同的触发器操作?
如果一个表的外键在 DELETE/UPDATE 操作上定义了U联Q则不能在该表上定义 INSTEAD OF DELETE/UPDATE 触发器?/p>
在触发器内可以指定Q意的 SET 语句。所选择?SET 选项在触发器执行期间有效Qƈ在触发器执行完后恢复C前的讄?/p>
与用存储过E一P当触发器Ȁ发时Q将向调用应用程序返回结果。若要避免由于触发器Ȁ发而向应用E序q回l果Q请不要包含q回l果?SELECT 语句Q也不要包含在触发器中进行变量赋值的语句。包含向用户q回l果?SELECT 语句或进行变量赋值的语句的触发器需要特D处理;q些q回的结果必d入允怿改触发器表的每个应用E序中。如果必d触发器中q行变量赋|则应该在触发器的开头?SET NOCOUNT 语句以避免返回Q何结果集?
DELETE 触发器不能捕?TRUNCATE TABLE 语句。尽?TRUNCATE TABLE 语句实际上是没有 WHERE 子句?DELETEQ它删除所有行Q,但它是无日志记录的,因而不能执行触发器。因?TRUNCATE TABLE 语句的权限默认授予表所有者且不可转让Q所以只有表所有者才需要考虑无意中用 TRUNCATE TABLE 语句规避 DELETE 触发器的问题?/p>
无论有日志记录还是无日志记录QWRITETEXT 语句都不Ȁz触发器?/p>
触发器中不允总?Transact-SQL 语句Q?/p>
ALTER DATABASE | CREATE DATABASE | DISK INIT |
DISK RESIZE | DROP DATABASE | LOAD DATABASE |
LOAD LOG | RECONFIGURE | RESTORE DATABASE |
RESTORE LOG |
说明 ׃ SQL Server 不支持系l表中的用户定义触发器,因此不要在系l表中创建用户定义触发器?/p>
SQL Server 允许为每个数据修改事ӞDELETE、INSERT ?UPDATEQ创建多个触发器。例如,如果对已?UPDATE 触发器的表执?CREATE TRIGGER FOR UPDATEQ则创建另一个更新触发器。在早期版本中,在每个表上,每个数据修改事gQINSERT、UPDATE ?DELETEQ只允许有一个触发器?
说明 如果触发器名UC同,?CREATE TRIGGERQ兼容别ؓ 70Q的默认行ؓ是在现有的触发器中添加其它触发器。如果触发器名称相同Q则 SQL Server q回一条错误信息。但是,如果兼容U别{于或小?65Q则使用 CREATE TRIGGER 语句创徏的新触发器将替换同一cd的Q何现有触发器Q即使触发器名称不同。有x多信息,请参?strong> sp_dbcmptlevel?
当在 sp_dboption 中启?recursive triggers 讄ӞSQL Server q允许触发器的递归调用?/p>
递归触发器允许发生两U类型的递归Q?
使用间接递归Ӟ应用E序更新?T1Q从而激发触发器 TR1Q该触发器更新表 T2。在q种情况下,触发?T2 激发ƈ更新 T1?/p>
使用直接递归Ӟ应用E序更新?T1Q从而激发触发器 TR1Q该触发器更新表 T1。由于表 T1 被更斎ͼ触发?TR1 再次Ȁ发,依此cL?/p>
下例既用了间接触发器递归Q又使用了直接触发器递归。假定在?T1 中定义了两个更新触发?TR1 ?TR2。触发器 TR1 递归地更新表 T1。UPDATE 语句?TR1 ?TR2 各执行一ơ。?TR1 的执行将触发 TR1Q递归Q和 TR2 的执行。给定触发器?inserted ?deleted 表只包含与唤醒调用触发器?UPDATE 语句相对应的行?/p>
说明 只有启用 sp_dboption ?recursive triggers 讄Q才会发生上q行为。对于ؓl定事g定义的多个触发器Qƈ没有定的执行顺序。每个触发器都应是自包含的?/p>
用 recursive triggers 讄只能止直接递归。若要也用间接递归Q请使用 sp_configure ?nested triggers 服务器选项讄?0?/p>
如果M触发器执行了 ROLLBACK TRANSACTION 语句Q则无论嵌套U是多少Q都不会q一步执行其它触发器?/p>
触发器最多可以嵌?32 层。如果一个触发器更改了包含另一个触发器的表Q则W二个触发器激z,然后该触发器可以再调用第三个触发器,依此cL。如果链中Q意一个触发器引发了无限@环,则会出嵌套U限Ӟ从而导致取消触发器。若要禁用嵌套触发器Q请?sp_configure ?nested triggers 选项讄?0Q关闭)。默认配|允许嵌套触发器。如果嵌套触发器是关闭的Q则也将用递归触发器,?sp_dboption ?recursive triggers 讄无关?/p>
SQL Server 允许 Transact-SQL 存储q程、触发器和批处理引用~译时不存在的表。这U能力称为gq名U解析。但是,如果 Transact-SQL 存储q程、触发器或批处理引用在存储过E或触发器中定义的表Q则只有当兼容别设|(通过执行 sp_dbcmptlevel 讄Q等?65 Ӟ才会在创建时发出警告。如果用批处理Q则在编译时发出警告。如果引用的表不存在Q将在运行时q回错误信息。有x多信息,请参?a ="javascript:hhobj_1.Click()">延迟名称解析和编?/a>?
CREATE TRIGGER 权限默认授予定义触发器的表所有者?strong>sysadmin 固定服务器角色成员以?db_owner ?db_ddladmin 固定数据库角色成员,q且不可转让?/p>
若要索表或视图中的数据,用户必须在表或视图中拥有 SELECT 语句权限。若要更新表或视囄内容Q用户必d表或视图中拥?INSERT、DELETE ?UPDATE 语句权限?/p>
如果视图中存?INSTEAD OF 触发器,用户必须在该视图中有 INSERT、DELETE ?UPDATE Ҏ(gu)Q以对该视图发出 INSERT、DELETE ?UPDATE 语句Q而不实际上是否在视图上执行了这L操作?/p>
当有囑֜ titles 表中d或更Ҏ(gu)据时Q下例将向客L昄一条消息?/p>
说明 消息 50009 ?sysmessages 中的用户定义消息。有兛_建用户定义消息的更多信息Q请参见 sp_addmessage?
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'reminder' AND type = 'TR')
DROP TRIGGER reminder
GO
CREATE TRIGGER reminder
ON titles
FOR INSERT, UPDATE
AS RAISERROR (50009, 16, 10)
GO
?titles 表更Ҏ(gu)Q下例将?sh)子邮g发送给指定的h?(MaryM)?/p>
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'reminder' AND type = 'TR')
DROP TRIGGER reminder
GO
CREATE TRIGGER reminder
ON titles
FOR INSERT, UPDATE, DELETE
AS
EXEC master..xp_sendmail 'MaryM',
'Don''t forget to print a report for the distributors.'
GO
׃ CHECK U束只能引用定义了列U或表U束的列Q表间的MU束Q在下例中是指业务规则)都必d义ؓ触发器?/p>
下例创徏一个触发器Q当插入或更新雇员工作?(job_lvls) Ӟ该触发器查指定雇员的工作U别Q由此决定薪_是否处于工作定义的范围内。若要获得适当的范_必须引用 jobs 表?/p>
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'employee_insupd' AND type = 'TR')
DROP TRIGGER employee_insupd
GO
CREATE TRIGGER employee_insupd
ON employee
FOR INSERT, UPDATE
AS
/* Get the range of level for this job type from the jobs table. */
DECLARE @min_lvl tinyint,
@max_lvl tinyint,
@emp_lvl tinyint,
@job_id smallint
SELECT @min_lvl = min_lvl,
@max_lvl = max_lvl,
@emp_lvl = i.job_lvl,
@job_id = i.job_id
FROM employee e INNER JOIN inserted i ON e.emp_id = i.emp_id
JOIN jobs j ON j.job_id = i.job_id
IF (@job_id = 1) and (@emp_lvl 10)
BEGIN
RAISERROR ('Job id 1 expects the default level of 10.', 16, 1)
ROLLBACK TRANSACTION
END
ELSE
IF NOT (@emp_lvl BETWEEN @min_lvl AND @max_lvl)
BEGIN
RAISERROR ('The level for job_id:%d should be between %d and %d.',
16, 1, @job_id, @min_lvl, @max_lvl)
ROLLBACK TRANSACTION
END
下例创徏两个触发器以说明延迟名称解析?
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'trig1' AND type = 'TR')
DROP TRIGGER trig1
GO
-- Creating a trigger on a nonexistent table.
CREATE TRIGGER trig1
on authors
FOR INSERT, UPDATE, DELETE
AS
SELECT a.au_lname, a.au_fname, x.info
FROM authors a INNER JOIN does_not_exist x
ON a.au_id = x.au_id
GO
-- Here is the statement to actually see the text of the trigger.
SELECT o.id, c.text
FROM sysobjects o INNER JOIN syscomments c
ON o.id = c.id
WHERE o.type = 'TR' and o.name = 'trig1'
-- Creating a trigger on an existing table, but with a nonexistent
-- column.
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'trig2' AND type = 'TR')
DROP TRIGGER trig2
GO
CREATE TRIGGER trig2
ON authors
FOR INSERT, UPDATE
AS
DECLARE @fax varchar(12)
SELECT @fax = phone
FROM authors
GO
-- Here is the statement to actually see the text of the trigger.
SELECT o.id, c.text
FROM sysobjects o INNER JOIN syscomments c
ON o.id = c.id
WHERE o.type = 'TR' and o.name = 'trig2'
下例创徏两个表:一?employeeData 表和一?auditEmployeeData 表。h力资源部的成员可以修?employeeData 表,该表包含敏感的雇员薪水信息。如果更改了雇员的社会保险号?(SSN)、年薪或银行帐户Q则生成审核记录q插入到 auditEmployeeData 审核表?/p>
通过使用 COLUMNS_UPDATED() 功能Q可以快速测试对q些包含敏感雇员信息的列所做的更改。只有在试图对表中的前 8 列所做的更改ӞCOLUMNS_UPDATED() 才v作用?/p>
USE pubs IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'employeeData') DROP TABLE employeeData IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'auditEmployeeData') DROP TABLE auditEmployeeData GO CREATE TABLE employeeData ( emp_id int NOT NULL, emp_bankAccountNumber char (10) NOT NULL, emp_salary int NOT NULL, emp_SSN char (11) NOT NULL, emp_lname nchar (32) NOT NULL, emp_fname nchar (32) NOT NULL, emp_manager int NOT NULL ) GO CREATE TABLE auditEmployeeData ( audit_log_id uniqueidentifier DEFAULT NEWID(), audit_log_type char (3) NOT NULL, audit_emp_id int NOT NULL, audit_emp_bankAccountNumber char (10) NULL, audit_emp_salary int NULL, audit_emp_SSN char (11) NULL, audit_user sysname DEFAULT SUSER_SNAME(), audit_changed datetime DEFAULT GETDATE() ) GO CREATE TRIGGER updEmployeeData ON employeeData FOR update AS /*Check whether columns 2, 3 or 4 has been updated. If any or all of columns 2, 3 or 4 have been changed, create an audit record. The bitmask is: power(2,(2-1))+power(2,(3-1))+power(2,(4-1)) = 14. To check if all columns 2, 3, and 4 are updated, use = 14 in place of >0 (below).*/ IF (COLUMNS_UPDATED() & 14) > 0 /*Use IF (COLUMNS_UPDATED() & 14) = 14 to see if all of columns 2, 3, and 4 are updated.*/ BEGIN -- Audit OLD record. INSERT INTO auditEmployeeData (audit_log_type, audit_emp_id, audit_emp_bankAccountNumber, audit_emp_salary, audit_emp_SSN) SELECT 'OLD', del.emp_id, del.emp_bankAccountNumber, del.emp_salary, del.emp_SSN FROM deleted del -- Audit NEW record. INSERT INTO auditEmployeeData (audit_log_type, audit_emp_id, audit_emp_bankAccountNumber, audit_emp_salary, audit_emp_SSN) SELECT 'NEW', ins.emp_id, ins.emp_bankAccountNumber, ins.emp_salary, ins.emp_SSN FROM inserted ins END GO /*Inserting a new employee does not cause the UPDATE trigger to fire.*/ INSERT INTO employeeData VALUES ( 101, 'USA-987-01', 23000, 'R-M53550M', N'Mendel', N'Roland', 32) GO /*Updating the employee record for employee number 101 to change the salary to 51000 causes the UPDATE trigger to fire and an audit trail to be produced.*/ UPDATE employeeData SET emp_salary = 51000 WHERE emp_id = 101 GO SELECT * FROM auditEmployeeData GO /*Updating the employee record for employee number 101 to change both the bank account number and social security number (SSN) causes the UPDATE trigger to fire and an audit trail to be produced.*/ UPDATE employeeData SET emp_bankAccountNumber = '133146A0', emp_SSN = 'R-M53550M'
WHERE emp_id = 101
GO
SELECT * FROM auditEmployeeData
GO
如果必须试影响到表中前 8 列以外的列的更新Ӟ必须使用 UBSTRING 函数试?COLUMNS_UPDATED q回的适当的位。下例测试媄?Northwind.dbo.Customers 表中的第 3、第 5 或第 9 列的更新?/p>
USE Northwind
DROP TRIGGER tr1
GO
CREATE TRIGGER tr1 ON Customers
FOR UPDATE AS
IF ( (SUBSTRING(COLUMNS_UPDATED(),1,1)=power(2,(3-1))
+ power(2,(5-1)))
AND (SUBSTRING(COLUMNS_UPDATED(),2,1)=power(2,(1-1)))
)
PRINT 'Columns 3, 5 and 9 updated'
GO
UPDATE Customers
SET ContactName=ContactName,
Address=Address,
Country=Country
GO
SELECT nickname,email
FROM testtable
WHERE name='张三'
(一) 选择列表
选择列表(select_list)指出所查询列,它可以是一l列名列表、星受表辑ּ、变?包括局部变量和全局变量){构成?
1、选择所有列
例如Q下面语句显Ctesttable表中所有列的数据:
SELECT *
FROM testtable
2、选择部分列ƈ指定它们的显C次?
查询l果集合中数据的排列序与选择列表中所指定的列名排列顺序相同?br> 例如Q?
SELECT nickname,email
FROM testtable
3、更改列标题
在选择列表中,可重新指定列标题。定义格式ؓQ?br> 列标?列名
列名 列标?br> 如果指定的列标题不是标准的标识符格式Ӟ应用引号定界符Q例如,下列语句使用汉字昄列标题:
SELECT 늧=nickname,?sh)子邮g=email
FROM testtable
4、删除重复行
SELECT语句中用ALL或DISTINCT选项来显C中符合条件的所有行或删除其中重复的数据行,默认为ALL。用DISTINCT选项Ӟ对于所有重复的数据行在SELECTq回的结果集合中只保留一行?
5、限制返回的行数
使用TOP n [PERCENT]选项限制q回的数据行敎ͼTOP n说明q回n行,而TOP n PERCENTӞ说明n是表CZ癑ֈ敎ͼ指定q回的行数等于总行数的癑ֈ之几?br> 例如Q?
SELECT TOP 2 *
FROM testtable
SELECT TOP 20 PERCENT *
FROM testtable
(?FROM子句
FROM子句指定SELECT语句查询及与查询相关的表或视图。在FROM子句中最多可指定256个表或视图,它们之间用逗号分隔?br> 在FROM子句同时指定多个表或视图Ӟ如果选择列表中存在同名列Q这时应使用对象名限定这些列所属的表或视图。例如在usertable和citytable表中同时存在cityid列,在查询两个表中的cityid时应使用下面语句格式加以限定Q?
SELECT username,citytable.cityid
FROM usertable,citytable
WHERE usertable.cityid=citytable.cityid
在FROM子句中可用以下两U格式ؓ表或视图指定别名Q?br> 表名 as 别名
表名 别名
(? FROM子句
FROM子句指定SELECT语句查询及与查询相关的表或视图。在FROM子句中最多可指定256个表或视图,它们之间用逗号分隔?br> 在FROM子句同时指定多个表或视图Ӟ如果选择列表中存在同名列Q这时应使用对象名限定这些列所属的表或视图。例如在usertable和citytable表中同时存在cityid列,在查询两个表中的cityid时应使用下面语句格式加以限定Q?
SELECT username,citytable.cityid
FROM usertable,citytable
WHERE usertable.cityid=citytable.cityid
在FROM子句中可用以下两U格式ؓ表或视图指定别名Q?br> 表名 as 别名
表名 别名
例如上面语句可用表的别名格式表示为:
SELECT username,b.cityid
FROM usertable a,citytable b
WHERE a.cityid=b.cityid
SELECT不仅能从表或视图中检索数据,它还能够从其它查询语句所q回的结果集合中查询数据?
例如Q?
SELECT a.au_fname+a.au_lname
FROM authors a,titleauthor ta
(SELECT title_id,title
FROM titles
WHERE ytd_sales>10000
) AS t
WHERE a.au_id=ta.au_id
AND ta.title_id=t.title_id
此例中,SELECTq回的结果集合给予一别名tQ然后再从中索数据?
(? 使用WHERE子句讄查询条g
WHERE子句讄查询条gQ过滤掉不需要的数据行。例如下面语句查询年龄大?0的数据:
SELECT *
FROM usertable
WHERE age>20
WHERE子句可包括各U条件运符Q?br> 比较q算W?大小比较)Q?gt;?gt;=??lt;?lt;=?lt;>?>?<
范围q算W?表达式值是否在指定的范?QBETWEEN...AND...
NOT BETWEEN...AND...
列表q算W?判断表达式是否ؓ列表中的指定?QIN (?,?......)
NOT IN (?,?......)
模式匚wW?判断值是否与指定的字W通配格式相符):LIKE、NOT LIKE
I值判断符(判断表达式是否ؓI?QIS NULL、NOT IS NULL
逻辑q算W?用于多条件的逻辑q接)QNOT、AND、OR
1、范围运符例:age BETWEEN 10 AND 30相当于age>=10 AND age<=30
2、列表运符例:country IN ('Germany','China')
3、模式匹配符例:常用于模p查找,它判断列值是否与指定的字W串格式相匹配。可用于char、varchar、text、ntext、datetime和smalldatetime{类型查询?br> 可用以下通配字符Q?br> 癑ֈ?Q可匚wLcd和长度的字符Q如果是中文Q请使用两个癑ֈ号即%%?br> 下划U_Q匹配单个Q意字W,它常用来限制表达式的字符长度?br> Ҏ(gu)号[]Q指定一个字W、字W串或范_要求所匚w对象为它们中的Q一个。[^]Q其取g[] 相同Q但它要求所匚w对象为指定字W以外的M个字W?br> 例如Q?br> 限制以Publishingl尾Q用LIKE '%Publishing'
限制以A开_LIKE '[A]%'
限制以A开头外QLIKE '[^A]%'
4、空值判断符例WHERE age IS NULL
5、逻辑q算W:优先UؓNOT、AND、OR
(?查询l果排序
使用ORDER BY子句Ҏ(gu)询返回的l果按一列或多列排序。ORDER BY子句的语法格式ؓQ?br> ORDER BY {column_name [ASC|DESC]} [,...n]
其中ASC表示升序Qؓ默认|DESC为降序。ORDER BY不能按ntext、text和image数据cdq行?br> 序?br> 例如Q?
SELECT *
FROM usertable
ORDER BY age desc,userid ASC
另外Q可以根据表辑ּq行排序?
二?联合查询
UNIONq算W可以将两个或两个以上上SELECT语句的查询结果集合合q成一个结果集合显C,x行联合查询。UNION的语法格式ؓQ?
select_statement
UNION [ALL] selectstatement
[UNION [ALL] selectstatement][...n]
其中selectstatement为待联合的SELECT查询语句?
ALL选项表示所有行合ƈ到结果集合中。不指定该项Ӟ被联合查询结果集合中的重复行只保留一行?
联合查询Ӟ查询l果的列标题为第一个查询语句的列标题。因此,要定义列标题必须在第一个查询语句中定义。要对联合查询结果排序时Q也必须使用W一查询语句中的列名、列标题或者列序号?
在用UNION q算W时Q应保证每个联合查询语句的选择列表中有相同数量的表辑ּQƈ且每个查询选择表达式应h相同的数据类型,或是可以自动它们{换ؓ相同的数据类型。在自动转换Ӟ对于数值类型,pȝ低_ֺ的数据类型{换ؓ高精度的数据cd?
在包括多个查询的UNION语句中,其执行顺序是自左臛_Q用括号可以改变这一执行序。例如:
查询1 UNION (查询2 UNION 查询3)
三、连接查?
通过q接q算W可以实现多个表查询。连接是关系数据库模型的主要特点Q也是它区别于其它类型数据库理pȝ的一个标志?
在关pL据库理pȝ中,表徏立时各数据之间的关系不必定Q常把一个实体的所有信息存攑֜一个表中。当索数据时Q通过q接操作查询出存攑֜多个表中的不同实体的信息。连接操作给用户带来很大的灵zL,他们可以在Q何时候增加新的数据类型。ؓ不同实体创徏新的表,后通过q接q行查询?
q接可以在SELECT 语句的FROM子句或WHERE子句中徏立,似是而非在FROM子句中指接时有助于将q接操作与WHERE子句中的搜烦条g区分开来。所以,在Transact-SQL中推荐用这U方法?
SQL-92标准所定义的FROM子句的连接语法格式ؓQ?
FROM join_table join_type join_table
[ON (join_condition)]
其中join_table指出参与q接操作的表名,q接可以对同一个表操作Q也可以对多表操作,对同一个表操作的连接又U做自连接?
join_type 指出q接cdQ可分ؓ三种Q内q接、外q接和交叉连接。内q接(INNER JOIN)使用比较q算W进行表间某(?列数据的比较操作Qƈ列出q些表中与连接条件相匚w的数据行。根据所使用的比较方式不同,内连接又分ؓ{D接、自然连接和不等q接三种。外q接分ؓ左外q接(LEFT OUTER JOIN或LEFT JOIN)、右外连?RIGHT OUTER JOIN或RIGHT JOIN)和全外连?FULL OUTER JOIN或FULL JOIN)三种。与内连接不同的是,外连接不只列Zq接条g相匹配的行,而是列出左表(左外q接?、右?叛_q接?或两个表(全外q接?中所有符合搜索条件的数据行?
交叉q接(CROSS JOIN)没有WHERE 子句Q它q回q接表中所有数据行的笛卡尔U,其结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以W二个表中符合查询条件的数据行数?
q接操作中的ON (join_condition) 子句指出q接条gQ它pq接表中的列和比较运符、逻辑q算W等构成?
无论哪种q接都不能对text、ntext和image数据cd列进行直接连接,但可以对q三U列q行间接q接。例如:
SELECT p1.pub_id,p2.pub_id,p1.pr_info
FROM pub_info AS p1 INNER JOIN pub_info AS p2
ON DATALENGTH(p1.pr_info)=DATALENGTH(p2.pr_info)
(一)内连?br> 内连接查询操作列Zq接条g匚w的数据行Q它使用比较q算W比较被q接列的列倹{内q接分三U:
1、等D接:在连接条件中使用{于?=)q算W比较被q接列的列|其查询结果中列出被连接表中的所有列Q包括其中的重复列?br> 2、不{连接: 在连接条件用除{于q算W以外的其它比较q算W比较被q接的列的列倹{这些运符包括>?gt;=?lt;=?lt;?>?<?lt;>?br> 3、自然连接:在连接条件中使用{于(=)q算W比较被q接列的列|但它使用选择列表指出查询l果集合中所包括的列Qƈ删除q接表中的重复列?br> 例,下面使用{D接列出authors和publishers表中位于同一城市的作者和出版C:
SELECT *
FROM authors AS a INNER JOIN publishers AS p
ON a.city=p.city
又如使用自然q接Q在选择列表中删除authors 和publishers 表中重复?city和state)Q?br> SELECT a.*,p.pub_id,p.pub_name,p.country
FROM authors AS a INNER JOIN publishers AS p
ON a.city=p.city
(?外连?br> 内连接时Q返回查询结果集合中的仅是符合查询条? WHERE 搜烦条g?HAVING 条g)和连接条件的行。而采用外q接Ӟ它返回到查询l果集合中的不仅包含W合q接条g的行Q而且q包括左?左外q接?、右?叛_q接?或两个边接表(全外q接)中的所有数据行。如下面使用左外q接论坛内容和作者信息连接v来:
SELECT a.*,b.* FROM luntan LEFT JOIN usertable as b
ON a.username=b.username
下面使用全外q接city表中的所有作者以及user表中的所有作者,以及他们所在的城市Q?
SELECT a.*,b.*
FROM city as a FULL OUTER JOIN user as b
ON a.username=b.username
(?交叉q接
交叉q接不带WHERE 子句Q它q回被连接的两个表所有数据行的笛卡尔U,q回到结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以W二个表中符合查询条件的数据行数。例Qtitles表中?cd书,而publishers表中?家出版社Q则下列交叉q接索到的记录数等?*8=48行?br> SELECT type,pub_name
FROM titles CROSS JOIN publishers
ORDER BY type