2012-09-20 49 views
1

比方說,我有一個包含一個varchar字段的表:構建動態T-SQL查詢在一個存儲過程

CREATE TABLE [MyTable] (
    [MyId] varchar(3) NOT NULL, 
    ..... 
) 

[身份識別碼]列包含像A1,A2連續alphanum值... A99,B1,B2..B99,C1等(直到Z99)。

我想要做的是從表中提取行,其中MyId字段匹配某些特定的前綴...例如,我想從系列A,C,P和X中獲取行。

我想用一個sproc動態構建基於參數中提供的前綴字母表的查詢。

我在想這樣的事情...

CREATE PROCEDURE [dbo].[uspFilterMyTable] 
    @prefixArray varchar(max) 
AS 
    ... -- split individual characters from @prefixArray into an array 

    SELECT * FROM [MyTable] 
    WHERE 
    [MyId] LIKE .... 
    OR 
    [MyId] LIKE .... -- iterate all characters from @prefixArray 

我想在存儲過程中,主要大宗將類似於下面的僞代碼:

DECLARE @sql nvarchar(max) 
-- iterate through all the characters 
SET @sql = 'SELECT * FROM [MyTable] WHERE [MyId] LIKE ' + @charInTheArray + '%' 
SET @sql = @sql + ' OR [MyId] LIKE ' + @nextCharInArray + '%' 


EXEC (@sql) 

以上proecedure會被稱爲是這樣的:

EXEC uspFilterMyTable("A,C,P,X") 

...或者可能是這樣的(如果它使分裂阿爾法賭注更容易):

EXEC uspFilterMyTable("ACPX") 

任何想法?指針?


更新: OK,這是我想出(從賈特拉帕蒂·夏爾馬借來[分割]功能):

-- [MyTable] contains these rows: 'A7', 'A87', 'B16', 'C51', 'H99', 'X12' 

-- the "input" parameter 
DECLARE @prefixArray NVARCHAR(100)= 'H,A,C' 

-- split the string into SQL wild-card patterns 
DECLARE charCursor CURSOR FOR 
    select items + N'%' from dbo.Split(@prefixArray, ',') 


OPEN charCursor; 
DECLARE @pattern CHAR(2) 

-- create temp table if necessary 
IF NOT EXISTS(SELECT * FROM TEMPDB.SYS.TABLES WHERE NAME LIKE '#tmpTable%') 
    CREATE TABLE #tmpTable ([Id] VARCHAR(3) NOT NULL) 

-- purge old data 
DELETE FROM #tmpTable 

FETCH NEXT FROM charCursor into @pattern 
WHILE @@FETCH_STATUS = 0 
BEGIN 
     --SELECT * INTO #tmpTable FROM [MyTable] WHERE [MyId] LIKE @pattern 
     Insert Into #tmpTable Select * FROM [MyTable] WHERE [MyId] LIKE @pattern 
    FETCH NEXT FROM charCursor into @pattern 
END 

CLOSE charCursor; 
DEALLOCATE charCursor; 

-- return the values 
SELECT * FROM #tmpTable  

這是醜陋的,我知道,但它的工作原理..任何提示即興代碼?

+0

你如何使用它?你從哪裏來的? –

+0

您使用的是什麼RDBMS,MS SQL Server,MySQL,Oracle,Postgre? – Yaroslav

+0

我實際上使用EF - 但我想保持業務邏輯在服務器端...此過程將返回只讀行,將被稱爲很多 – invarbrass

回答

2

首先應該創建以下函數,然後使用該查詢這樣

SELECT * FROM [MyTable] WHERE [MyId] in (select items from dbo.split(@prefixArray,',')) 



CREATE FUNCTION [dbo].[Split](@String varchar(8000), @Delimiter char(1))   
returns @temptable TABLE (items varchar(8000))   
as   
begin   
    declare @idx int   
    declare @slice varchar(8000)   

    select @idx = 1   
    if len(@String)<1 or @String is null return   

    while @idx!= 0   
    begin   
     set @idx = charindex(@Delimiter,@String)   
     if @idx!=0   
     set @slice = left(@String,@idx - 1)   
    else   
     set @slice = @String   

     if(len(@slice)>0)  
     insert into @temptable(Items) values(@slice)   

     set @String = right(@String,len(@String) - @idx)   
     if len(@String) = 0 break   
     end  
    return   
    end 
1

我會建議你使用表值參數來調用存儲過程。我想你是從.net來的。但我認爲EF將無法處理它,儘管您可能會檢查它。如果沒有,我認爲最好的方法是首先將字符串解析爲臨時表或表值,然後再與它結合。

隨着TVP:

CREATE PROCEDURE [dbo].[uspFilterMyTable] 
    @prefixArray tvp_idlist readonly 
as 
    select 
    t.* 
    from MyTable t 
    join @prefixArray pa on pa.id = t.myid 

有分流功能(你選擇,你在網絡上找到許多例子)

CREATE PROCEDURE [dbo].[uspFilterMyTable] 
    @prefixArray varchar(max) 
as 

    create @prefixArray tvp_idlist 
    insert into @prefixArray (id) 
    select id from dbo.myCustomSplit(@prefixArray,',') 


    select 
    t.* 
    from MyTable t 
    join @prefixArray pa on pa.id = t.myid 

如果這兩種情況下@prefixArray是一個表變量標識= varchar(3)

作爲一個編輯,經過一點挖掘,似乎只需一點點工作,EF就可以很好地與TVP合作。選中此項:Entity Framework Stored Procedure Table Value Parameter。所以最好的辦法是直接發送一個表到你的存儲過程,然後發送一個字符串來解析。

2

這裏有一個基於XML的又好又快分割方法:

DECLARE @str NVARCHAR(100)= 'A1,B3,C4,B12,K19', @separator VARCHAR(1)= ',' 
DECLARE @SplitedList TABLE (code NVARCHAR(30)) 

DECLARE @XMLList XML 
SET @XMLList=CAST('<i>'+REPLACE(@str, @separator,'</i><i>')+'</i>' AS XML) 

INSERT INTO @SplitedList 
SELECT x.i.value('(./text())[1]','varchar(100)') 
FROM @XMLList.nodes('i') x(i) 

SELECT * FROM @SplitedList 

結果將與分裂值的表:

code 
A1 
B3 
C4 
B12 
K19 

從這裏你可以繼續使用此表根據你的程序,並使用LIKE與你一起提供原始表格。