SQL Server中Merge子句、CTE、CONCAT、FORMAT函数用法

Merge子句

把源数据合并到目标表

点击查看代码
CREATE TABLE a
(keycol INT PRIMARY KEY,
col1 INT NOT NULL,
col2 INT NOT NULL,
col3 INT NOT NULL);
CREATE TABLE b
(keycol INT PRIMARY KEY,
col1 INT NOT NULL,
col2 INT NOT NULL,
col3 INT NOT NULL);
INSERT INTO a VALUES (1,0,0,0),(2,0,0,0);
INSERT INTO b VALUES (1,1,1,1),(3,3,3,3);
INSERT INTO a VALUES (3,0,0,0),(4,0,0,0);
INSERT INTO b VALUES (4,1,1,1),(5,3,3,3);
SELECT * FROM dbo.a
SELECT * FROM dbo.b
merge a using
b
on a.[keycol]=b.[keycol]
when matched then
update set a.col1=b.col1,a.col2=b.col2,a.col3=b.col3
when not matched then
insert ([keycol],col1,col2,col3) values (b.[keycol],b.col1,b.col2,b.col3)
when NOT matched BY SOURCE
THEN DELETE;


output用法

点击查看代码
create table test(
id int identity(1,1) primary key,
name varchar(50),
age int,
addr varchar(50),
birth datetime
)
DROP TABLE dbo.test
insert into test(name,age) output inserted.* values('小明',20),('小张',18),('小王',18)
delete from test output deleted.* where age=18
update test set name='age_18_update',birth=GETDATE() output deleted.* ,inserted.*where age=18
--总结:
--deleted- 更新前的数据(update,delete)
--inserted-更新后的数据(update,insert)
--注意:不能在一个INSERT语句中引用DELETED,也不能在一个DELETED语句中引用INSERTED,
--因为这些虚拟表在这两种情况下逻辑上是没有意义的,所以SQL Server不会去创建。


CTE表达式

点击查看代码
CREATE TABLE Products (
Product_ID int NOT NULL,
Product_Name varchar (25),
Price money NULL,
CONSTRAINT PK_Products PRIMARY KEY NONCLUSTERED (Product_ID)
)
GO
INSERT INTO Products (Product_ID, Product_Name, Price) VALUES (1, 'Widgets', 25)
INSERT INTO Products (Product_ID, Product_Name, Price) VALUES (2, 'Gadgets', 50)
INSERT INTO Products (Product_ID, Product_Name, Price) VALUES (3, 'Thingies', 75)
INSERT INTO Products (Product_ID, Product_Name, Price) VALUES (4, 'Whoozits', 90)
INSERT INTO Products (Product_ID, Product_Name, Price) VALUES (5, 'Whatzits', 5)
INSERT INTO Products (Product_ID, Product_Name, Price) VALUES (6, 'Gizmos', 15)
INSERT INTO Products (Product_ID, Product_Name, Price) VALUES (7, 'Widgets', 24)
INSERT INTO Products (Product_ID, Product_Name, Price) VALUES (8, 'Gizmos', 36)
INSERT INTO Products (Product_ID, Product_Name, Price) VALUES (9, 'Gizmos', 36)
GO
--示例一(基本用法):
--CET 可以看做是一个临时的结果集
--使用公用表达式可以让语句更加清晰简练
WITH MyCTE(ID, Name)
as
(
SELECT Product_ID as ID, Product_Name as Name
from Products
)
select * from MyCTE
--可以在一个语句中多次引用公用表表达式(CTE)
;WITH MyCTE1(ID, Name)
as
(
SELECT Product_ID as ID, Product_Name as Name
from Products WHERE Product_ID<5
)
,MyCTE2(ID, Name)
AS
(
SELECT Product_ID as ID, Product_Name as Name
from Products WHERE Product_ID>5
)
SELECT * FROM MyCTE1
UNION ALL
SELECT * FROM MyCTE2
--示例二(分页):
with MyCTE(ID, Name, RowID)
as
(
select Product_ID as ID, Product_Name as Name,
Row_Number() over (order by Product_ID) as RowID
from Products
)
select * from MyCTE where RowID between 1 and 5
--示例三(递归)
DECLARE @Table TABLE (Id INT, IdParent INT);
INSERT INTO @Table VALUES (1, NULL);
INSERT INTO @Table VALUES (2, 1);
INSERT INTO @Table VALUES (3, 1);
INSERT INTO @Table VALUES (4, 2);
INSERT INTO @Table VALUES (5, 3);
INSERT INTO @Table VALUES (6, 3);
INSERT INTO @Table VALUES (7, 3);
INSERT INTO @Table VALUES (8, 4);
INSERT INTO @Table VALUES (9, 5);
--SELECT * FROM @Table
;WITH CTE AS
(
SELECT
T.Id,
T.IdParent,
1 AS [Level]
FROM @Table AS T
WHERE T.IdParent IS NULL
UNION ALL
SELECT
T.Id,
T.IdParent,
CTE.[Level] + 1 AS [Level]
FROM @Table AS T
JOIN CTE ON CTE.Id = T.IdParent
)
SELECT * FROM CTE ORDER BY [Level]
--示例四(递归查询)
--如果只是想获得某一个父级下的所有子节点,那么cet 是很不错的选择!
CREATE TABLE CITYINFO(
ID INT NOT NULL PRIMARY KEY IDENTITY(1,1),
NAME VARCHAR(100),
PID INT
)
GO
INSERT INTO CITYINFO VALUES('四川',0)
INSERT INTO CITYINFO VALUES('成都',1)
INSERT INTO CITYINFO VALUES('眉山',1)
INSERT INTO CITYINFO VALUES('乐山',1)
INSERT INTO CITYINFO VALUES('重庆',0)
INSERT INTO CITYINFO VALUES('合川',5)
INSERT INTO CITYINFO VALUES('长寿',5)
INSERT INTO CITYINFO VALUES('江津',5)
INSERT INTO CITYINFO VALUES('尚义',3)
INSERT INTO CITYINFO VALUES('悦心',3)
WITH CTE AS
(
SELECT * FROM CITYINFO WHERE NAME='四川'
UNION ALL
SELECT A.ID,A.NAME,A.PID FROM CITYINFO AS A JOIN CTE AS B
ON A.PID=B.ID
)
SELECT * FROM CTE


concat与format

** 注意:只能在2012以及才能用**

点击查看代码
--1、concat()函数用于将两个字符串连接起来,形成一个单一的字符串。
SELECT CONCAT ('ab','cd')
SELECT 1+NULL
SELECT CONCAT ('ab',null,'cd')
--或者是系统函数获取当前时间后直接与字符串连接在一起。
SELECT CONCAT ('Current system datetime is',' ',CURRENT_TIMESTAMP)
--2、FORMAT函数
--FORMAT(column_name,format) column_name 要格式化的字段。format 规定格式。
--时间格式化
Select FORMAT(getdate(),'yyyy-MM-dd')
--数字前补0
Select FORMAT(1,'000000') -- 000001
--使用 FORMAT 函数将日期/时间和数字值格式化为识别区域设置的字符串
--https://docs.microsoft.com/zh-cn/sql/t-sql/functions/format-transact-sql?view=sql-server-ver15
DECLARE @d DATE = '11/22/2020';
SELECT FORMAT( @d, 'd', 'en-US' ) 'US English'
,FORMAT( @d, 'd', 'en-gb' ) 'Great Britain English'
,FORMAT( @d, 'd', 'de-de' ) 'German'
,FORMAT( @d, 'd', 'zh-cn' ) 'Simplified Chinese (PRC)';
SELECT FORMAT( @d, 'D', 'en-US' ) 'US English'
,FORMAT( @d, 'D', 'en-gb' ) 'Great Britain English'
,FORMAT( @d, 'D', 'de-de' ) 'German'
,FORMAT( @d, 'D', 'zh-cn' ) 'Chinese (Simplified PRC)';
DECLARE @d DATE = GETDATE();
SELECT FORMAT( @d, 'dd/MM/yyyy', 'en-US' ) AS 'Date'
,FORMAT(123456789,'###-##-####') AS 'Custom Number';

——————
———————

时间戳timestamp

点击查看代码
CREATE TABLE [tb_Ts]([TS] TIMESTAMP)
INSERT INTO [tb_Ts]([TS]) VALUES(DEFAULT)
INSERT INTO [tb_Ts]([TS]) VALUES(DEFAULT)
INSERT INTO [tb_Ts]([TS]) VALUES(DEFAULT)
INSERT INTO [tb_Ts]([TS]) VALUES(DEFAULT)
GO
--1)、timestamp转换为十六进制或bigint
SELECT TS
,CAST(TS AS VARBINARY(8)) AS 'timestamp转十六进制'
,CONVERT(BIGINT,TS) AS 'timestamp转bigint类型'
FROM tb_Ts
--2)、也可以将bigint转换为timestamp类型
DECLARE @TsValue BIGINT=10001
SELECT TS
,CAST(TS AS VARBINARY(8)) AS 'timestamp转十六进制'
,CONVERT(BIGINT,TS) AS 'timestamp转bigint类型'
FROM tb_Ts
WHERE
TS<=CONVERT(TIMESTAMP,@TsValue)

——————
——————

STUFF函数

点击查看代码
--以下示例在第一个字符串abcdef中删除从第2个位置(字符b)开始的三个字符,
--然后在删除的起始位置插入第二个字符串,从而创建并返回一个字符串。
SELECT STUFF('abcdef', 2, 3, 'ijklmn');
GO
DECLARE @Users TABLE(Id INT, [Name] VARCHAR(MAX));
INSERT INTO @Users VALUES(1, 'Name 1');
INSERT INTO @Users VALUES(2, 'Name 2');
INSERT INTO @Users VALUES(3, 'Name 3');
INSERT INTO @Users VALUES(4, 'Name 4');
INSERT INTO @Users VALUES(5, 'Name 5');
-- SQLServer   CAST -- 转换数据类型  逗号表示分割 。      
--STUFF 函数理解 -- 第一个就是字符串 FOR XML PATH('') 必须用 ,
--第二个参数 负数或0空字符串,指定删除 或者插入的开始位置,
--第三个参数 -- 指定删除的长度,为0表示在之前的长度插入,要替换的字符串    
SELECT STUFF((SELECT CAST(Id AS NVARCHAR(MAX))+','
FROM @Users
WHERE Id>=3
GROUP BY Id
FOR XML PATH('')), 1, 1, 2) AS ids;
--sqlserver函数 剔除字符串最后一个字符
DECLARE @str VARCHAR(MAX)
SET @str='2,4,5,'
SELECT LEFT(@STR,LEN(@STR)-1)


GROUP_CONCAT

合并多行为一行

点击查看代码
CREATE TABLE #YourTable ([ID] INT, [Name] CHAR(1), [Value] INT)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'A',4)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'B',8)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (2,'C',9)
--方法一,采用stuff函数
SELECT
[ID],
STUFF((
SELECT ', ' + [Name] + ':' + CAST([Value] AS VARCHAR(MAX))
FROM #YourTable
WHERE (ID = Results.ID)
FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
,1,2,'') AS NameValues
FROM #YourTable Results
GROUP BY ID
--方法二:GROUP_CONCAT函数
SELECT id,
dbo.GROUP_CONCAT(Name + ':' + CAST([Value] AS VARCHAR(MAX))) AS NameValues
FROM #YourTable
GROUP BY id;
DROP TABLE #YourTable
posted @   Raymon撸码记  阅读(262)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示