自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

SQL Server解惑——查詢條件IN中能否使用變量

運(yùn)維 數(shù)據(jù)庫運(yùn)維
在SQL Server的查詢條件中,能否在IN里面使用變量呢?如果可以的話,有沒有需要注意的地方或一些限制呢?

本文轉(zhuǎn)載自微信公眾號(hào)「DBA閑思雜想錄」,作者瀟湘隱者 。轉(zhuǎn)載本文請聯(lián)系DBA閑思雜想錄公眾號(hào)。   

在SQL Server的查詢條件中,能否在IN里面使用變量呢?如果可以的話,有沒有需要注意的地方或一些限制呢?在回答這個(gè)問題前,我們先來看看這個(gè)例子:

  1. IF EXISTS (SELECT 1 FROM sys.objects WHERE name='TEST' AND type='U'
  2. BEGIN 
  3.  DROP TABLE TEST; 
  4. END 
  5. GO 
  6. CREATE TABLE TEST ( ID INTNAME VARCHAR(16) ); 
  7. GO 
  8.  
  9. INSERT INTO dbo.TEST 
  10. SELECT 1, 'a'  UNION ALL 
  11. SELECT 2, 'b'  UNION ALL 
  12. SELECT 3, 'c'  UNION ALL 
  13. SELECT 4, 'a,b'UNION ALL 
  14. SELECT 5, '''b'',''c''' UNION ALL 
  15. SELECT 6, '''b'
  16. GO 

如下所示,如果查詢條件里面,變量只有一個(gè)值,此時(shí)SQL是正常的。

  1. DECLARE @name VARCHAR(16); 
  2. SET @name='a'
  3.  
  4. SELECT * FROM TEST WHERE name IN (@name); 
  5. GO 
  6.  
  7. DECLARE @name VARCHAR(16); 
  8. SET @name='a,b'
  9.  
  10. SELECT * FROM TEST WHERE name IN (@name); 
  11. GO 

如果我們想在查詢條件IN里面輸入多個(gè)值呢?假如有這樣的一個(gè)需求,一個(gè)變量里面包含b和c的值,現(xiàn)在用'b|c’作為條件傳入,對其進(jìn)行拆分為變量'b'和'c', 想查出name=b 和name=c的記錄,如下截圖所示,SQL其實(shí)并沒有按你所“設(shè)想/預(yù)想”的查出對應(yīng)記錄,而是將ID=5的記錄查出來了

  1. DECLARE @name1 VARCHAR(16); 
  2. DECLARE @name2 VARCHAR(16); 
  3. SET @name1='b|c'
  4. SET @name2=REPLACE(@name1,'|',''','''
  5. SELECT @name2 
  6.  
  7. SELECT * FROM TEST WHERE name IN (('''' + @name2 + '''')); 

下面這個(gè)SQL也是同樣的結(jié)果。

  1. DECLARE @name1 VARCHAR(16); 
  2. DECLARE @name2 VARCHAR(16); 
  3. SET @name1='b|c'
  4. SET @name2='''' + REPLACE(@name1,'|',''',''') +'''' 
  5. SELECT @name2 
  6.  
  7. SELECT * FROM TEST WHERE name IN (@name2 ); 

為什么出現(xiàn)了這樣的結(jié)果呢?查了大量的官方文檔,沒有看到關(guān)于這個(gè)問題的介紹和解釋。如果一定要解釋上面現(xiàn)象的情況的話,那么是因?yàn)镾ELECT * FROM TEST WHERE name IN (@name2 ); 其實(shí)轉(zhuǎn)化為了SELECT * FROM TEST WHERE name =@name2; 也就是說,上面SQL并不會(huì)按你所“設(shè)想”的邏輯運(yùn)算。而是做了一個(gè)轉(zhuǎn)換,為什么說是這樣的一個(gè)轉(zhuǎn)換呢?當(dāng)然這也是一個(gè)猜想,上面構(gòu)造的例子也是為了側(cè)面驗(yàn)證這個(gè)猜想,另外,上面兩個(gè)SQL實(shí)際執(zhí)行計(jì)劃的參數(shù)列表(Parameter List)也側(cè)面印證了這個(gè)猜想(如下截圖所示)。如果執(zhí)行計(jì)劃解析成我們想要的結(jié)果,那么Parameter List應(yīng)該是'b' 和‘c'

解決方案:

1:使用動(dòng)態(tài)SQL

使用動(dòng)態(tài)SQL解決問題,似乎沒啥好說的,如下例子所示:

  1. DECLARE @sql_cmd NVARCHAR(max); 
  2. DECLARE @name VARCHAR(16); 
  3.  
  4. SET @name='b|c'
  5. SET @sql_cmd='SELECT * FROM TEST WHERE name IN (''' + REPLACE(@name,'|',''',''') +''');' 
  6.  
  7. EXEC sp_executesql @sql_cmd; 

2:使用臨時(shí)表或表變量

以這個(gè)例子來說,就是將字符串拆分,放入臨時(shí)表或表變量,然后關(guān)聯(lián)表也好,在IN里面使用子查詢也OK。

3:借助STRING_SPLIT()

  1. DECLARE @name VARCHAR(16); 
  2.  
  3. SET @name='b|c'
  4. SELECT *FROM  test WHERE name IN (SELECT value FROM STRING_SPLIT(@name'|')) 

注意:STRING_SPLIT函數(shù)只有較高版本才支持,SQL Server 2017或SQL Server 2016部分版本支持。

4:借助XML函數(shù)來解決問題

  1. DECLARE @name VARCHAR(16); 
  2. DECLARE @xml_para XML; 
  3.  
  4. SET @name = 'b|c'
  5. SET @xml_para = CAST(( '<A>' + REPLACE(@name'|''</A><A>') + '</A>' ) AS XML); 
  6.  
  7.  
  8. SELECT  * 
  9. FROM    dbo.TEST 
  10. WHERE   NAME IN ( SELECT    A.value('.''varchar(max)'AS [Column
  11.                   FROM      @xml_para.nodes('A'AS FN ( A ) ); 

 

責(zé)任編輯:武曉燕 來源: DBA閑思雜想錄
相關(guān)推薦

2021-02-03 08:01:35

SQLServerLIKE

2010-11-09 15:18:37

SQL Server多

2010-10-21 11:10:57

SQL Server查

2011-07-04 14:28:18

SQL Server分區(qū)

2010-10-21 10:28:13

SQL Server查

2010-11-09 13:28:13

SQL SERVER查

2021-01-07 09:20:08

SQL字符串Server

2010-07-16 08:50:00

SQL Server表

2010-09-14 16:36:34

SQL SERVER查

2010-06-29 17:52:02

SQL Server嵌

2011-03-29 13:22:07

SQL Server臨時(shí)表表變量

2011-08-14 23:26:30

激光打印機(jī)常見問題

2010-09-03 14:56:12

SQLSELECT語句

2012-07-11 23:10:49

SQL Server數(shù)據(jù)庫

2010-09-06 17:11:14

SQL函數(shù)

2021-12-14 07:05:00

SQL語句數(shù)據(jù)庫

2010-07-22 16:02:29

2010-09-28 14:59:29

sql查詢

2011-08-12 09:14:08

SQL Server創(chuàng)建數(shù)據(jù)庫創(chuàng)建表

2010-10-21 10:42:30

SQL Server查
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)