数据库基础
模式schema,关于数据库和表的布局及特性的信息 |
主键 primary key一列或一组列,其值能唯一标识表中每一行。应该总是定义主键。 |
主键条件: 1.任意两行都不具有相同的主键值。 2.每一行都必须具有一个主键值(主键列不允许NULL值)。 3.主键列中的值不允许修改或更新。 4.主键值不能重用,如果某行从表中删除,它的主键不能赋给以后的行。 |
多条SQL语句用分号;分隔,不区分大小写,使用空格都会被忽略。 |
数据类型及其名称是SQL数据库不兼容的一个主要原因 |
SQL注释: --这是一条注释 #这是一条注释 /*这是一条注释*/ |
检索数据 – Select
检索单个列: SELECT列名 FROM表名 注:返回数据没有特定顺序 |
检索多个列: SELECT列名1,列名2,… FROM表名 |
检索所有列: SELECT * FROM表名 |
检索不同的值: SELECT DISTINCT列名 FROM表名 注:DISTINCT只返回不同的值(过滤掉重复的),必须放在列名前面,且作用于后边所有的列。 |
限制返回的行数 (数据库不同语法不同) SQL Server:SELECT TOP 5列名 FROM表名 PostgreSQL:SELECT列名FROM表名 LIMIT 5 |
排序检索数据
关系型数据库设计理论认为,如果不明确规定排序顺序,则不应该假定检索出的数据的顺序有任何意义 |
按单个列排序: SELECT列名 FROM表名 ORDER BY列名 注:指定一条ORDER BY子句时候,应该保证它是SELECT语句的最后一条子句。 否则会出现错误信息。 |
按多个列排序: SELECT列名1,列名2, 列名3 FROM 表名ORDER BY列名1,列名2 注释:先按照列名1排序,如果列名1相同再按列名2排序。 |
按照位置排序: SELECT列名1,列名2, 列名3 FROM 表名ORDER BY 2,3 注释:按照SELECT清单里面的第2列(列名2)和第3列(列名3)排序。最好不要这么用,因为不明确给出列名可能造成用错列,再就是如果对SELECT清单做修改后容易忘记修改响应的列号。 |
升降序排序:ASC DESC 升序ASC不需要指定,因为是默认 DESC/ASC应用于直接位于其前面的列名,而不是所有列。如果想在多个列上进行降序排序,必须对每一个列指定DESC关键字。 SELECT列名1,列名2,列名3 FROM表名 ORDER BY 列名1 DESC,列名2 DESC 注:A和a相同么?a位于B之前还是Z之后?答案取决于数据的设置方式。 |
过滤数据
WHERE子句 SELECT列名1,列名2 FROM表名 WHERE 列名=值
|
尽量在数据库端过滤数据。而让客户端应用(或开发语言)处理数据将会极大地影响应用的性能,并且使所创建的应用完全不具备可伸缩性。此外,如果在客户端过滤数据,服务器不得不通过网络发送多余的数据,导致网络带宽的浪费。 |
WHERE操作符 = (等于) <> (不等于) !=(不等于) < (小于) <= (小于等于) !< (不小于) > (大于) >= (大于等于) !> (不大于) BETWEEN (在指定的两个值之间) IS NULL (为NULL) 注:并非所有的数据库都支持这些操作符,参见相关文档。 |
BETWEEN AND例子 SELECT prod_name, prod_price FROM Products WHERE prod_price BETWEEN 5 and 10 |
IS NULL例子 SELECT cust_name FROM Customers WHERE cust_email IS NULL |
高级数据过滤
WHERE + AND指定同时满足多个条件 SELECT prod_id,prod_price,prod_name FROM Products WHERE vend_id = ‘DLL01’AND prod_price <= 4 |
WHERE + OR指定匹配任何一个条件即可 SELECT prod_name, prod_price FROM Products WHERE vend_id =‘DLL01’OR vend_id = ‘BRS01’; |
注:AND的优先级大于OR 可以使用圆括号对多个操作符进行明确分组 SELECT prod_name, prod_price FROM Products WHERE(vend_id =‘DLL01’OR vend_id = ‘BRS01’)AND prod_price >= 10 |
WHERE + IN IN操作符用来指定条件范围,范围中的每个条件都可以进行匹配。IN取一组由逗号分隔,括在圆括号中的合法值。 SELECT prod_name, prod_price FROM Products WHERE vend_id IN (‘DLL01’,’BRS01’) ORDER BY prod_name; 注:WHERE+IN与WHERE+OR功能相同,但执行更快。 |
NOT操作符 WHERE子句中的NOT操作符有且只有一个功能,那就是否定其后边所跟的任何条件。一般可用不等(<>,!=)来代替 SELECT prod_name FROM Products WHERE NOT vend_id = ‘DLL01’ ORDER BY prod_name; 等于 SELECT prod_name FROM Products WHERE vend_id <> ‘DLL01’ ORDER BY prod_name;
|
通配符过滤
使用通配符搜索,必须使用LIKE操作符。且通配符搜索只能用于文本字段(字符串),而不能用于非文本类型。 |
%通配符 表示任何字符出现任意次数 SELECT prod_id, prod_name FROM Products WHERE prod_name LIKE ‘Fish%’ 表示以Fish开头的任意字符串。 注:%通配符能匹配0个字符,但不能匹配NULL |
通配符可以在任意位置使用,且可以使用多个通配符。 SELECT prod_id, prod_name FROM Products WHERE prod_name LIKE ‘%bean%’
SELECT prod_id, prod_name FROM Products WHERE prod_name LIKE ‘F%y’
|
下划线_通配符 只匹配单个字符 SELECT prod_id, prod_name FROM Products WHERE prod_name LIKE ‘_ _ inch’ |
方括号[]通配符 用来指定一个字符集,它必须匹配指定位置(通配符位置)的一个字符 SELECT prod_id, prod_name FROM Products WHERE prod_name LIKE ‘[JM]%’ 注表示所有以J或者M开头的prod_name
使用^或NOT给[]取反 SELECT prod_id, prod_name FROM Products WHERE prod_name LIKE ‘[^JM]%’
SELECT prod_id, prod_name FROM Products WHERE NOT prod_name LIKE ‘[JM]%’
|
使用通配符搜索耗时更长,且不要把通配符置于开始处。把通配符置于开始处,搜索起来是最慢的。 |
创建计算字段
计算字段并不实际存在数据库表中。计算字段是运行时在SELECT语句内创建的。 就像定义的一个变量!!! |
在SQL语句内可完成的许多转换和格式化工作都可以直接在客户端应用程序完成,但一般来说,在数据库服务器上完成这些操作比在客户端中完成要快得多。 |
拼接字段: 使用+(Access, SQL Server), || (DB2,Oracle, PostgreSQL, SQLite, Open Office Base)或者Concat( MySQL, MariaDB ) SELECT vend_name + ‘ (’ + vend_country + ‘)’ FROM Venders ORDER BY vend_name
SELECT vend_name || ‘ (’ || vend_country + ‘)’ FROM Venders ORDER BY vend_name
SELECT Concat(vend_name +,‘ (’ , vend_country , ‘)’) FROM Venders ORDER BY vend_name
|
使用TRIM(), RTRIM(), LTRIM()来去掉字段中的填充空格。 SELECT RTRIM(vend_name) + ‘ (’ + RTRIM(vend_country) + ‘)’ FROM Venders ORDER BY vend_name
|
别名是一个字段或者值的替换名,使用AS关键字定义别名。这样所有的客户端应用都可以按照这个名称引用这个列。 SELECT RTRIM(vend_name) + ‘ (’ + RTRIM(vend_country) + ‘)’ AS vend_title FROM Venders ORDER BY vend_name
|
使用计算字段,客户使用计算字段就像使用其他列一样。 SELECT prod_id,quantity,item_price, quantity* item_price AS expanded_price FROM OrderItems WHERE order_num = 200008 |
省略了FROM的SELECT就是简单的访问和处理表达式。例如SELECT 3*2,将返回6. SELECT Now(),返回的是当前日期和时间。 |
使用函数处理数据
每一个DBMS都有特定的函数。事实上,只有少数几个函数被所有主要的DBMS等同地支持。 |
UPPER(): SELECT vend_name, UPPER(vend_name) AS vend_name_upcase FROM Vendors ORDER BY vend_name; |
常用文本处理函数 LEFT()返回字符串左边的字符 LENGTH()返回字符串的长度 LOWER()将字符串转为小写 LTRIM()去掉字符串左边的空格 RTRIM()去掉字符串右边的空格 RIGHT()返回字符串右边的字符 SOUNDEX()返回字符串的SOUNDEX值 UPPER() 将字符串转为大写 注:SOUNDEX是一个将任何文本串转换为描述其语音表示的字母数字模式的算法 |
日期处理函数 SELECT order_num FROM Orders WHERE DATEPART(‘yyyy’,order_date)=2012; DATEPART()函数返回日期的某一部分,不同数据库这个函数可能不同。 |
数值处理函数 ABS()返回一个数的绝对值 COS()返回一个角度的余弦 EXP()返回一个数的指数值 PI() 返回圆周率 SIN()返回一个角度的正弦 SQRT()返回一个数的平方根 TAN() 返回一个角度的正切 |
汇总数据
聚集函数:对某些行运行的函数,计算并返回一个值 SQL中的聚集函数 AVG()返回某列的平均值 COUNT()返回某列的行数 MAX()返回某列的最大值 MIN()返回某列的最小值 SUM()返回某列值之和 |
AVG() AVG()用于返回特定列(单列)的平均值。如果需要多个列的平均值,则用多个AVG();如果需列中指定行的平均值则需加上WHERE. AVG()会忽略值为NULL的行。 SELECT AVG(prod_price) AS avg_price FROM Products
SELECT AVG(prod_price) AS avg_price FROM Products WHERE vend_id = ‘DLL01’ |
COUNT()函数 用于计数。可利用COUNT()确定表中行的数目或符合特定条件的行的数目。 COUNT(*)统计表中的所有行数,包括含NULL的行。 SELECT COUNT(*) AS num_cust FROM Customers;
COUNT(column)统计某列中不包括NULL的行。 SELECT COUNT(cust_email) AS num_cust FROM Customers; |
MAX() SELECT MAX(prod_price) AS max_price FROM Products; |
MIN() SELECT MIN(prod_price) AS min_price FROM Products; |
SUM() SELECT SUM(item_price*quantity) AS total_price FROM OrderItems WHERE order_num = 20005; |
AVG(),SUM(),MIN(),MAX(),COUNT()对所有行进行计算可传入ALL或者什么都不传。 |
聚集函数对只包含不同的值,指定DISTINCT参数 SELECT SUM(DISTINCT prod_price) AS sum_price FROM Products WHERE vend_id = ‘DLL01’ |
组合聚集函数 SELECT COUNT(*) AS num_items MIN(prod_price) AS price_min, MAX(prod_price) AS price_max, AVG(prod_price) AS price_avg FROM Products; |
分组数据
创建分组:GROUP_BY SELECT vend_id, COUNT(*) AS num_prods FROM Products GROUP BY vend_id; 注:使用GROUP BY创建分组后,聚集(比如COUNT)就是针对每个分组而不是所有。比如这里的num_prods就是分组后每个分组中的行数。 |
GROUP BY规定 1.GROUP BY子句可以包含任意数目的列,因而可以对分组进行嵌套。 2.如果GROUP BY子句中嵌套了分组,数据将在最后指定的分组上进行汇总。也就是在建立分组时,指定的所有列都一起计算。 3.GROUP BY子句中列出的每一列都必须是检索列或有效的表达式。 4.重点:除了聚集函数以外,SELECT语句中的每一列都必须在GROUP BY子句中给出。 5.重点:GROUP BY语句必须出现在WHERE子句之后,ORDER BY子句之前。 |
WHERE可以被HAVING取代。唯一差别是,WHERE过滤行,而HAVING过滤分组。 |
HAVING过滤分组 SELECT cust_id, COUNT(*) AS orders FROM Orders GROUP BY cust_id HAVING COUNT(*) >=2; |
同时使用WHERE和HAVING SELECT vend_id, COUNT(*)AS num_prods FROM Products WHERE prod_price >= 4 GROUP BY vend_id HAVING COUNT(*) >= 2; |
SELECT子句中必须遵循的次序 SELECT FROM WHERE GROUP BY HAVING ORDER BY |
使用子查询
子查询:嵌套其他查询的查询 |
子查询总是从内向外处理 SELECT cust_id FROM Orders WHERE order_num IN (SELECT order_num FROM OrderItems WHERE prod_id = ‘RGAN01’); |
对于嵌套的子查询的数目没有限制,不过在实际使用时由于性能的限制,不能嵌套太多的子查询。 |
作为子查询的SELECT语句只能查询单个列。企图检索多个列将返回错误。而外层SELECT没有限制。 |
子查询作为计算字段: SELECT cust_name, cust_state, (SELECT COUNT(*) FROM Orders WHERE Orders.cust_id = Customers.cust_id) AS orders FROM Customers ORDER BY cust_name; |
联结表
关系表:关系表的设计就是把信息分解成多个表,一类数据一个表。各个表之间通过某些共同的值相互关联,所以才叫关系型数据库。 |
联结:联结是一种机制,用来在一条SELECT语句中关联表,检索出存在于多个表中的数据。 |
内联结(等值联结) SELECT vend_name, prod_name, prod_price FROM Vendors, Products WHERE Vendors.vend_id = Products.vend_id; 注:在引用的列可能出现歧义时,必须使用完全限定列名,即一个句点分割表名和列名。 如果没有指定联结条件即WHERE,则第一个表中的每一行将与第二个表中的每一行配对,返回笛卡尔积。 |
内联结的另一种实现方式 SELECT vend_name, prod_name, prod_price FROM Vendors INNER JOIN Products ON Vendors.vend_id = Products.vend_id; |
联结多个表 SELECT vend_name, prod_name, prod_price,quantity FROM Vendors, Products, OrderItems WHERE Vendors.vend_id = Products.vend_id AND OrderItems.prod_id = Products.prod_id ; 联结多个表注意联结的表越多,性能下降的越厉害。 |
多做实验 执行任一给定的SQL操作一般不止一种方法。很少有绝对正确或绝对错误的方法。性能可能受操作类型,所用的数据库,表中的数据量,是否存在索引或主键等条件的影响。因此有必要实验不同的选择机制,找出最适合具体情况的方法。 |
创建高级联结
给表起别名,但表别名不能返回给客户端 SELECT cust_name, cust_contact FROM Customers AS C, Orders AS O, OrderItems AS OI WHERE C.cust_id = O.cust_id AND OI.order_num = O.order_num AND prod_id = ‘RGAN01’; |
自联结来代替子查询 对于许多数据库而言,处理联结查询速度远比子查询快得多。应该试一下两种方法,那个更好。 子查询: SELECT cust_id, cust_name, cust_contact FROM Customers WHERE cust_name = (SELECT cust_name FROM Customers WHERE cust_contact = ‘Jim’);
替换的自联结: SELECT c1.cust_id, c1.cust_name, c1.cust_contact FROM Customers AS c1, Customers AS c2 WHERE c1.cust_name = c2.cust_name AND c2.cust_contact = ‘JIM’; |
外联结:即全部选择左边或右边表的所有行,即左外联结,右外联结。 |
左外联结 SELECT Customers.cust_id, Orders.order_num FROM Customers LEFT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id; 即左边Customers这个表的所有行都会被选择。 |
右外联结 SELECT Customers.cust_id, Orders.order_num FROM Customers RIGHT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id; 即右边Orders表的所有行都会被选择 |
全联结 SELECT Customers.cust_id, Orders.order_num FROM Customers FULL OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id;
|
联结中使用聚集函数 SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_ord FROM Customers INNER JOIN Orders ON Customers.cust_id = Orders.cust_id;
|
组合查询
复合查询:通过UNION操作符,将多条SELECT语句组合成一个结果集。 |
UNION使用很简单,即把UNION加在两个SELECT之间 SELECT cust_name, cust_contact,cust_email FROM Customers WHERE cust_state IN (‘IL’,’IN’,’MI’) UNION SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_name = ‘Fun4All’; |
UNION使用规则 1.UNION必须由两条或两条以上的SELECT语句组成。 2.UNION中的每个查询必须包含相同的列,表达式或聚集函数,不过各个列不需要以相同的次序列出。 3.列数据类型必须兼容。 |
UNION查询结果集自动去掉重复的行,如果不想去掉重复,则用UNION ALL。 |
UNION只能用一个ORDER BY,且必须位于最后一个SELECT语句之后,对整个结果集进行排序。 SELECT cust_name, cust_contact,cust_email FROM Customers WHERE cust_state IN (‘IL’,’IN’,’MI’) UNION SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_name = ‘Fun4All’ ORDER BY cust_name, cust_contact; |
插入数据
INSERT插入完整的一行 INSERT INTO Customers VALUES(‘1000006’,’Tony’,123,NULL); 但这样不安全,且不易扩展,尽量避免这样用
更安全且易扩展的写法: INSERT INTO Customers(cust_id,cust_name,cust_zip,cust_email) VALUES(‘1000006’,’Tony’,123,NULL); |
INSERT插入部分行 INSERT INTO Customers(cust_id,cust_name) VALUES(‘1000006’,’Tony’); 即只给某些列提供值,其他列使用默认值或者NULL。前提是该表允许默认值或NULL,否则报错。 |
将SELECT结果插入表中SELECT + INSERT: INSERT INTO Customers(cust_id,cust_name,cust_zip,cust_email) SELECT cust_id,cust_name,cust_zip,cust_email FROM CustNew; 注:1. SELECT和INSERT列名不需要一致,只是对应位置插入。 2.无论SELECT返回多少行,都会INSERT,即可多行插入。 |
SELECT+INTO将一个表中的部分列或者全部列复制到另一个表中 SELECT * INTO CustCopy FROM Customers; |
更新和删除数据
使用UPDATE/DELETE一定要小心,注意别更新/删除了所有行。 |
UPDATE更新某一列 UPDATE Customers SET cust_email = ‘fadfa@163.com’ WHERE cust_id = ‘10006’; |
UPDATE更新多个列 UPDATE Customers SET cust_email = ‘fadfa@163.com’, cust_contact = ‘Sam’ WHERE cust_id = ‘10006’; |
UPDATE更新某列值为NULL,前提是允许NULL UPDATE Customers SET cust_email = NULL WHERE cust_id = ‘10006’; |
DELETE删除某一行 DELETE FROM Customers WHERE cust_id = ‘10006’; |
使用外键防止删除某个关系需要用的行,所以总要定义外键。 |
删除所有行:使用TRUNCATE TABLE语句,而不要用DELETE(慢)。 |
创建和操作表
使用交互式工具时,实际上就是使用SQL语句。工具会自动生成并执行相应的SQL语句。 |
CREATE TABLE创建表 CREATE TABLE Products ( prod_id CHAR(10) NOT NULL, prod_name CHAR(254) NOT NULL, prod_desc VARCHAR(1000) NULL, prod_price DECIMAL(8,2) NOT NULL DEFAULT 0.1, prod_nickname CHAR(254) ); 注意: 1.表名必须不存在,否则会出错。 2.同时可以指定该列可以为NULL或不可以为NULL,默认可以为NULL(上例最后一行没指定,所以为可以为NULL)。 3.同时可以指定默认值,使用DEFAULT. |
各数据库获得日期的不同方式 Access NOW() DB2 CURRENT_DATE MySQL CURRENT_DATE() Oracle SYSDATE PostgreSQL CURRENT_DATE SQL Server GETDATE() SQLLite date(‘now’)
|
ALTER TABLE给已有表增加列 ALTER TABLE Vendors ADD Vend_phone CHAR(20); |
删除列 ALTER TABLE Vendors DORP COLUMN vend_phone; 注对于复杂的表结构一般需要手动删除过程。 |
删除表 DROP TABLE CustCopy; 如果跟其他表有关系(外键)则不能删除。 |
视图
视图:虚拟的表,只包含查询(理解成查询的结果,但只在使用时才动态生成)。 |
视图仅仅是用来查看存储在别处数据的一种设施。视图本身不包含数据,因此返回的数据是从其他表中检索出来的。在添加或更改这些表中的数据时,视图将返回改变过的数据。 |
视图不包含数据,每次使用视图时,都必须处理查询执行时需要的所有检索。如果你用多个联结和过滤创建复杂的视图或者嵌套了视图,性能可能会下降的很厉害。 |
视图常见应用: 1.重用SQL语句 2.简化复杂的SQL操作 3.使用表的一部分而不是整个表 4.保护数据 5.更改数据格式和表示 |
创建视图语句CREATE VIEW CREATE VIEW ProductCustomer AS SELECT cust_name, cust_contact, prod_id FROM Customers, Orders, OrderItems, WHERE Customers.cust_id = Orders.cust_id AND OrderItems.order_num = Orders.order_num; |
使用视图简化复杂的联结(接上) SELECT cust_name, cust_contact FROM ProductCustomer WHERE prod_id = ‘RGAN’; |
使用视图重新格式化检索出的数据 CREATE VIEW VendorLocations AS SELECT RTRIM(vend_name)||’(‘ || RTRIM(vend_country)|| ‘)’ AS vend_title FROM Vendors;
SELECT * FROM VendorLocations; |
使用视图过滤不想要的数据 CREATE VIEW CustomerEMailList AS SELECT cust_id, cust_name, cust_email FROM Customers WHERE cust_email IS NOT NULL;
SELECT * FROM CustomerEMailList; |
使用视图与计算字段 CREATE VIEW OrderItemsExpanded AS SELECT order_num, prod_id, quantity, item_price, quantity*item_price AS expanded_price FROM OrderItems;
SELECT * FROM OrderItemsExpanded WHERE order_num = 20008; |
存储过程
存储过程:为了以后使用而保存的一条或多条SQL语句)(类似于函数)。 |
执行存储过程 EXECUTE AddNewProduct(‘JIM’,’Stuffed Eiffel Tower’, 6.49); |
SQL Server定义和执行存储过程例子 CREATE PROCEDURE MailingListCount AS DECLARE @cnt INTEGER SELECT @cnt = COUNT(*) FROM Customers WHERE NOT cust_email IS NULL; RETURN @cnt; 执行: DECLARE @ReturnValue INT EXECUTE @ReturnValue = MailingListCount; SELECT @ReturnValue; |
事务处理
事务处理:确保成批的SQL要么完全执行,要么完全不执行,来维护数据库的完整性。 |
事务处理术语: 事务:指一组SQL语句。 回退:指撤销指定SQL语句的过程。 提交:指将未存储的SQL语句结果写入数据库表。 保留点:指事务处理中设置的临时占位符,可以对它发布回退。 |
事务处理用于INSERT,UPDATE和DELETE(删改插).但不能用于CREATE,SELECT和DROP. |
事务处理的开始和结束 BEGIN TRANSACTION … COMMIT TRANSACTION |
ROLLBACK后不接保留点的话,会撤销整个事务即完全回退。 |
游标
游标cursor:用于检索出来的行中前进或者后退一行或多行。 |
使用游标步骤: 1.创建游标: DECLARE CustCursor CURSOR FOR SELECT * FROM Customers WHERE cust_email IS NULL 2.打开游标: Open CustCursor …. 3.从添有游标的数据中取出各行。 4.关闭游标。 |
高级SQL特性
约束:管理如何插入或处理数据库数据的规则 |
主键:是一种特殊的约束,用来保证一列或一组列中的值是唯一的,而且永不改动。 |
满足下列条件的列可用于主键 1.任意两行的主键值都不相同 2.每行都具有一个主键值,即列中不允许NULL值。 3.包含主键值的列从不修改或更新。 4.主键值不能重用,如果从表中删除某一行,其主键值不能分给新行。 |
用PRIMARY KEY来指定主键 CREATE TABLE Vendors ( vend_id CHAR(10) NOT NULL PRIMARY KEY, … ); |
外键:表中的一列,其值必为另一个表的主键。外键是保证引用完整性的及其重要的部分。 定义外键用REFERENCES CREATE TABLE Vendors ( vend_id CHAR(10) NOT NULL PRIMARY KEY, … cust_id CHAR(10) NOT NULL REFERENCES Customers(cust_id) ); |
唯一约束:保证一列或一组列中的数据是唯一的!用UNIQUE关键字定义。想要唯一又不希望用主键。 |
检查约束:保证一列中的数据满足指定条件,用关键字check. |
索引:用来排序数据以加快搜索和排序操作的速度。但降低了插入,修改删除的性能,且占用空间大。 定义索引 CREATE INDEX prod_name_ind ON Products(prod_name); |
触发器:特定的数据库活动发生时自动执行。触发器可以与特定表上的INSERT,UPDATE和DELETE操作或组合相关联。 |