SQL Server温故系列(1):SQL 数据操作 CRUD 之增删改合
- 1、插入語句 INSERT INTO
- 1.1、用 INSERT 插入單行數據
- 1.2、用 INSERT 插入多行數據
- 1.3、用 INSERT 插入子查詢結果行
- 1.4、INSERT 小結及特殊字段插入方法
- 2、刪除語句 DELETE
- 2.1、用 DELETE 刪除表中指定行
- 2.2、用 TRUNCATE TABLE 高效清空表
- 3、更新語句 UPDATE
- 4、合并語句 MERGE
- 5、用 TOP 子句限制受影響的行
- 6、用 OUTPUT 子句返回受影響的數據
- 7、本文小結
毋庸置疑,開發者最常用的數據庫技術就是 SQL 了,即便是 ORM 大行其道的今天也常常需要寫 SQL 語句。而 SQL 語句中最常用的就是增刪改查了,本系列就先對增刪改查語句來個系統的回顧吧!
1、插入語句 INSERT INTO
1.1、用 INSERT 插入單行數據
INSERT INTO 的作用是向表中添加新行,語法如下:
INSERT INTO table-name(column1,column2,...column-n) VALUES(value1,value2,...value-n);譬如要向好學生表中添加 1 條數據,示例如下:
INSERT INTO T_GoodStudents(Name,Birthday) VALUES('李爾','1990-01-09'); -- 顯示指定要插入字段如果按表中的字段順序給出全部字段的值,那么就不用顯示指定字段了,示例如下:
INSERT INTO T_GoodStudents VALUES(1,'邱晨',1,'1990-09-01');1.2、用 INSERT 插入多行數據
INSERT INTO 還可以一次向表中添加多條數據,如要一次性向學生表中添加 3 條數據,示例如下:
INSERT INTO T_GoodStudents(Name,Gender,Birthday) VALUES('張三',1,'1993-03-03'),('李四',1,'1994-04-04'),('王五',1,'1995-05-05');注意:在插入全部字段時,插入多行數據也可以像插入單行數據那樣省略字段列表,但必須確保各行之間的數據個數相同、類型兼容。
1.3、用 INSERT 插入子查詢結果行
向表中插入數據時,既可以通過 VALUES 子句顯示地列出插入值,也可以通過 SELECT 子句來獲得插入值。語法如下:
INSERT INTO target-table-name SELECT columns FROM source-table-name;該語句的效果類似于把一張表的數據復制到另一張表,要復制的字段和行都可以顯示的指定。當要將大量行從源表傳輸到目標表中時,該語句還能夠以最小日志記錄的方式高效的完成。示例如下:
INSERT INTO T_GoodStudents SELECT Id,Name,Gender,Birthday FROM T_Students; -- 完全復制(數據) INSERT INTO T_GoodStudents(Name,Gender) SELECT Name,Gender FROM T_Students; -- 指定部分字段復制 INSERT INTO T_GoodStudents(Name) SELECT Name FROM T_Students WHERE Gender=1; -- 指定部分數據復制如果目標表和源表的表結構相同,子查詢的字段列表還可以用 * 來代替。在指定字段復制時,無需表結構相同,只要對應字段的數據類型兼容即可,甚至還可以沒有源表,一個子查詢就夠了。示例如下:
INSERT INTO T_GoodStudents SELECT 999,'李敏',0,'1991-02-02'; -- 插入 1 條(來自子查詢的)數據INSERT INTO T_GoodStudents(Id,Name,Birthday) SELECT 11,'王陽','1991-03-02' UNION ALL SELECT 12,'李玉','1991-07-02' UNION ALL SELECT 13,'鄭爽','1991-02-02'; -- 插入 3 條(來自子查詢的)數據1.4、INSERT 小結及特殊字段插入方法
在使用 INSERT INTO 語句向表中插入新行時,除了帶默認值和帶標識的字段,其它必填的字段都需要顯示的給出值,而非必填字段不給值時 SQL Server 默認會給它一個 NULL 值,也可以顯示的給定一個 NULL 值。
1.4.1、將數據插入有默認值的字段中 時,如果沒有為指定了默認值的字段指定值,那么新行的該字段的值將會是默認值。假如要添加一行,有默認值的字段就讓它為默認值,沒有默認值的字段就讓它為 NULL,那么就可以用如下語句:
INSERT INTO T_GoodStudents DEFAULT VALUES;1.4.2、將數據插入到標識列中 時,無論是指定插入字段還是不指定插入字段,都無需考慮標識列,因為 SQL Server 的關系引擎會根據標識增量和標識種子自動為標識列賦值。如果需要為標識列指定值,就需要先把 IDENTITY_INSERT 打開,然后才能插入,示例如下:
SET IDENTITY_INSERT T_Students ON; -- 當前會話有效,別的會話不受影響 INSERT INTO T_Students(Id,Name) VALUES(-1,'李哈哈'); -- Id 字段為標識列注意1:必須在 INTO 子句中顯示列出標識列,否則即便在 VALUES 子句中提供所有字段的值也還是會報錯。
注意2:如果想在當前會話中繼續像默認情況那樣忽略標識列,就需要把 IDENTITY_INSERT 關掉,示例如下:
SET IDENTITY_INSERT T_Students OFF;2、刪除語句 DELETE
2.1、用 DELETE 刪除表中指定行
DELETE 語句用于從表中刪除現有行,語法如下:
DELETE FROM table-name WHERE delete-conditions;WHERE 子句的作用在于確定刪除哪些行,示例如下:
DELETE FROM T_GoodStudents WHERE Id >= 20; -- 刪除 Id 大于等于 20 的數據 DELETE FROM T_GoodStudents WHERE Id NOT IN(SELECT Id FROM T_Students); -- 刪除 Id 不在學生表中的數據注意:在 PL/SQL 中可以方便的給要刪數據的表取個別名,以便限定 WHERE 子句中的字段,但在 T-SQL 中卻不能直接給 DELETE 語句中要刪數據的表取別名。如果想要限定刪除條件中的字段,可以用如下兩種寫法:
DELETE FROM T_Students WHERE T_Students.Id = 4; -- 直接用表名來限定(條件字段少時比較方便) DELETE T_Students FROM T_Students t WHERE t.Id = 5; -- 在 DELETE 子句中加上表名(條件字段多時更方便)理論上 DELETE 語句是可以不帶 WHERE 子句的,但這個操作很危險,因為它意味著刪除表中所有行。
2.2、用 TRUNCATE TABLE 高效清空表
TRUNCATE TABLE 用于刪除表中的所有行,如果表中有標識列,標識列會重新開始計數,相當于清空了整個表。語法如下:
TRUNCATE TABLE table-name;如要清空好學生表,示例如下:
TRUNCATE TABLE T_GoodStudents;注意:盡管不帶 WHERE 條件的 DELETE 語句就可以刪除表中所有數據,但 TRUNCATE TABLE 比 DELETE 的速度更快,使用的系統資源和事務日志資源也更少。
3、更新語句 UPDATE
UPDATE 語句用于更新指定表中的現有數據,語法如下:
UPDATE table-name SET column1 = value1,column2 = value2,...column-n = value-n WHERE update-conditions;WHERE 子句用于限定哪些行需要被更新,如果不帶 WHERE 子句就會更新所有行,當然這很危險,一般也沒有這種需求。可以一次更新一個字段,也可以一次更新多個字段,字段的值可以顯示給出,也可以是個表達式,表達式中還可以引用表中的字段。示例如下:
UPDATE T_GoodStudents SET Name = '王娜' WHERE Id = 7; -- 更新一個字段的值 UPDATE T_GoodStudents SET Name = '徐莉',Gender = 0 WHERE Id = 7; -- 更新多個字段的值 UPDATE T_GoodStudents SET Birthday = GETDATE()-10 WHERE Id = 7; -- 用表達式給字段賦值 UPDATE T_GoodStudents SET Birthday = Birthday-10 WHERE Id = 7; -- 在表達式中引用字段 UPDATE T_GoodStudents SET Name += '學生' WHERE Id > 3; -- 在姓名后面加上"學生"3.1、SET 子句內包含子查詢時,示例如下(把班級名更新到學生備注中):
UPDATE T_Students SET Remark = (SELECT t.Name FROM T_Classes t WHERE t.Id = ClassId);注意1:上例中沒有 WHERE 子句,這意味著(不論學生表中的 ClassId 是否在班級表中出現過)都會更新整個學生表,ClassId 未在班級表中出現過的學生備注會被更新為 NULL。盡管看似簡單,但筆者就曾在職場中多次遇到工作數年的技術人員因忽略這點而誤改了數據。
注意2,如果恰好兩個表中的關聯字段名相同,大概率上會出問題或報錯,為了穩妥起見需要限定一下字段。在 Oracle 中可以方便的通過表別名來限定,然而 SQL Server 卻不支持給 UPDATE 語句的 UPDATE 子句中的表取別名,但可以直接通過表名來限定字段。示例如下:
UPDATE T_GoodStudents SET Name = (SELECT t.Name FROM T_Students t WHERE t.Id = T_GoodStudents.Id) WHERE T_GoodStudents.Id IN(SELECT Id FROM T_Students); -- 將學生表的姓名同步到好學生表3.2、WHERE 子句內含子查詢時,示例如下(將單科考試 3 次不及格的寫入到學生備注中):
UPDATE T_Students SET Remark = '單科3次不及格' WHERE Id IN(SELECT t.StudentId FROM T_ExamResults t WHERE t.Scores < 60 GROUP BY t.StudentId,t.CourseId HAVING COUNT(1) >= 3 );3.3、帶 FROM 子句的 UPDATE 語句,示例如下(把所有學生最近一次考試的總成績更新到學生備注中):
UPDATE T_Students SET Remark = t2.SumScore FROM T_Students t1 JOIN(SELECT t.StudentId,SUM(t.Scores) SumScore FROM T_ExamResults t WHERE t.Counts = (SELECT MAX(Counts) FROM T_ExamResults) GROUP BY t.StudentId ) t2 ON t1.Id=t2.StudentId;如果只需要更新部分學生,比如僅更新 1 班的學生,就可以在 ON 后面直接加AND t1.ClassId=1,或者在整個語句后面加WHERE t1.ClassId=1。有意思的是,這種 UPDATE 語句即便沒有 WHERE 條件,也不會對未在 FROM 子句中限定的行產生影響。
4、合并語句 MERGE
相比較 INSERT、DELETE、UPDATE 和 SELECT 來說,MERGE 出現的要晚一些,但也有十多年了,各大 SQL 數據庫在 21 世紀頭幾年陸續提供了對 MERGE 的支持。簡單來說,MERGE 語句就是對增刪改查的“合并”,使得可以在一個語句內根據查詢的匹配情況來決定是否要增、刪或改某些數據,而不必再寫冗長的邏輯判斷和事物處理了。語法如下:
MERGE target-table-name USING source-table-expressions ON merge-search-conditions WHEN MATCHED AND clause-search-conditions THEN merge-matched WHEN NOT MATCHED AND clause-search-conditions THEN merge-not-matched;使用 MERGE 在單個語句中對表執行 INSERT 或 UPDATE 操作,示例如下:
MERGE T_Students AS target USING(SELECT '朱丹丹',0) AS source (Name,Gender) ON(target.Name = source.Name) WHEN MATCHED THEN UPDATE SET Gender = source.Gender WHEN NOT MATCHED THEN INSERT(Name,Gender) VALUES(source.Name,source.Gender);使用 MERGE 在單個語句中對表執行 INSERT、DELETE 或 UPDATE 操作,示例如下:
MERGE T_Students AS target USING(SELECT '劉天寶',1,'1990-09-09') AS source (Name,Gender,Birthday) ON(target.Name = source.Name) WHEN MATCHED AND target.Birthday < source.Birthday THEN DELETE WHEN MATCHED THEN UPDATE SET target.Gender = source.Gender,target.Birthday = source.Birthday WHEN NOT MATCHED THENINSERT(Name,Gender,Birthday) VALUES(source.Name,source.Gender,source.Birthday);5、用 TOP 參數限制受影響的行
熟悉 SQL Server 的開發者估計都知道 TOP 參數可以用來限制查詢語句的返回行數,但其實 TOP 參數不僅可以限制 SELECT 的結果集,還以限制受 INSERT、DELETE 或 UPDATE 影響的行。
5.1、帶 TOP 參數的 INSERT 語句,示例如下(隨機將 3 個女學生添加到好學生表):
INSERT TOP(3) INTO T_GoodStudents SELECT t.Id,t.Name,t.Gender,t.Birthday FROM T_Students t WHERE t.Gender = 0;如果想要按某種特定的順序插入數據,譬如要把年齡最大的 3 個學生添加到好學生表,示例如下:
INSERT INTO T_GoodStudents SELECT TOP(3) t.Id,t.Name,t.Gender,t.Birthday FROM T_Students t ORDER BY t.Birthday;5.2、帶 TOP 參數的 DELETE 語句,示例如下(隨機刪除 3 個女學生):
DELETE TOP(3) FROM T_GoodStudents WHERE Gender = 0;如果想要按某種特定的順序刪除數據,譬如要刪除年齡最大的 3 個學生的信息,示例如下:
DELETE FROM T_GoodStudents WHERE Id IN(SELECT TOP(3) t.Id FROM T_GoodStudents t ORDER BY t.Id DESC);5.3、帶 TOP 參數的 UPDATE 語句,示例如下(隨機將 3 個男學生的性別更新為 0):
UPDATE TOP(3) T_Students SET Gender = 0 WHERE Gender = 1;如果想要按某種特定的順序更新數據,譬如要將年齡最大的 3 個男學生的性別更新為 0,示例如下:
UPDATE T_GoodStudents SET Gender = 0 FROM(SELECT TOP(3) t1.Id FROM T_GoodStudents t1 ORDER BY t1.Id DESC) t2 WHERE T_GoodStudents.Id = t2.Id;6、用 OUTPUT 子句返回受影響的數據
試想一下,如果需要在插入的一條數據的同時返回這條數據,或者在刪除一條數據的同時備份這條數據,我們當然可以用多條簡單語句來共同完成,并且通過事務來確保操作的原子性。但其實這類需求可以通過 OUTPUT 子句來更好的完成,而且一個語句就能搞定,不必加事務,因為它本身就具備原子性。
在使用 OUTPUT 返回數據時,需要借助 INSERTED 或 DELETED 來引用字段值。INSERTED 用來引用插入操作或更新操作添加的值,DELETED 用來引用刪除操作或更新操作刪除的值。在 INSERT 語句中不能訪問 DELETED,在 DELETE 語句中不能訪問 INSERTED,在 UPDATE 語句中兩個都能訪問。示例如下:
INSERT T_GoodStudents OUTPUT inserted.* VALUES(7,'高鵬',1,'1979-11-11'); -- 插入 1 條信息并輸出 DELETE TOP(1) FROM T_GoodStudents OUTPUT deleted.Id,deleted.Name; -- 刪除 1 條信息并輸出UPDATE TOP(2) T_GoodStudents SET Gender = 1 OUTPUT deleted.Name,inserted.Name,deleted.Gender,inserted.Gender; -- 更新 2 條信息并輸出還可以結合 INTO 把 OUTPUT 返回的數據插入到另一張表中,示例如下:
INSERT T_GoodStudents OUTPUT inserted.* INTO T_GoodStudents VALUES(9,'黃強',1,'1999-11-11'); DELETE TOP(1) FROM T_GoodStudents OUTPUT deleted.* INTO T_GoodStudents; UPDATE TOP(2) T_GoodStudents SET Gender = 1 OUTPUT deleted.* INTO T_GoodStudents;7、本文小結
本文主要講述了 T-SQL 語句中的 INSERT、DELETE、UPDATE 和 MERGE 共 4 個 DML 語句及其子句,以及一個 DDL 語句 TRUNCATE TABLE,而且這幾個語句都是實際開發中特別常用的語句。
在 Oracle 中總是給表取別名是個很好的習慣,但 SQL Server 的增刪改語句均不支持對目標表取別名,只有合并語句和查詢語句支持別名。不過 SQL Server 中的所有 DML 語句都支持用表名來限定字段名。
有些讀者可能會有疑問“為什么 SQL Server 管理工具生成的語句總是要給對象名前后加上中括號?”。盡管不好看,但的確有道理,因為它可以防止用戶自定義名稱跟系統關鍵字沖突。譬如你要用 USER 做表名或字段名,就得用中括號包裹一下。另外,如果想用某些特殊符號來命名也需要用中括號包裹,但一般不建議這么做,太變態了!
如果你不幸遇到頭尾帶空格的對象名,你會發現只寫空格以外的名稱部分是訪問不到該對象的,這種情況也可以用中括號來解決。如果你有修改權限的話建議還是把空格刪掉吧,太惡心了!假如學生表前后有空格,查詢示例如下:
SELECT * FROM [ T_Students ];本文參考鏈接:
- 1、SQL Server 2016 INSERT
- 2、SQL Server 2016 DELETE
- 3、SQL Server 2016 TRUNCATE TABLE
- 4、SQL Server 2016 UPDATE
- 5、SQL Server 2016 MERGE
- 6、SQL Server 2016 TOP
- 7、SQL Server 2016 OUTPUT
去導航目錄篇下載創建本系列博文通用庫表及數據的 SQL 語句
本文鏈接:http://www.cnblogs.com/hanzongze/p/tsql-crud.html
版權聲明:本文為博客園博主 韓宗澤 原創,作者保留署名權!歡迎通過轉載、演繹或其它傳播方式來使用本文,但必須在明顯位置給出作者署名和本文鏈接!個人博客,能力有限,若有不當之處,敬請批評指正,謝謝!
轉載于:https://www.cnblogs.com/hanzongze/p/tsql-crud.html
總結
以上是生活随笔為你收集整理的SQL Server温故系列(1):SQL 数据操作 CRUD 之增删改合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows Java、Tomcat、
- 下一篇: mysql事务隔离级别与设置