2016-11-06 47 views
0

我希望能夠編寫一個SQL Server存儲過程,它將根據參數選擇列,並且選擇順序應該基於另一個參數。SQL Server存儲過程只能按特定順序選擇活動列

例如,我有一個表tblStaging,它有幾列(名稱,日期,Addr1,Addr2,Addr3)。我想用這個表來創建一個使用存儲過程的XML。該存儲過程會簡單地從該表中選擇的列和XML語法顯示出來,是這樣的:

SELECT 
    Name, date, Addr1, Addr2, Addr3 
FROM 
    tblStaging 
FOR XML RAW ('TRAN'), ROOT ('SEPA'), ELEMENTS; 

現在,我想使這個存儲過程配置的,讓用戶通過2個參數,即「主動」國旗和'訂單'。活動:1或0,將決定是否在XML模式中選擇一個字段。順序:1,2,3,4 ..將決定字段的選擇順序,例如。如果將「名稱」設置爲Active = 1和Order = 2,則它將被選中,但不是作爲第一個元素,而是作爲XML中的第二個元素。

什麼是實現這一目標的最佳方式是什麼?不知道我是否應該有每列2個參數並要求用戶爲每個參數傳遞一個值,如果表中有10列(= 20個參數),那麼有點麻煩。

提前致謝!

+0

需要更多信息。數據的目的是什麼?你需要所有的結果還是一些?有沒有理由不能在框架級別處理訂單? –

回答

1

我已經爲你寫了一個工作代碼。在生產系統中使用它之前,您可能需要進一步開發它,因爲它未經過測試並受SQL注入的限制。

@OrderBy:你也可以使用序號所允許的SQL(order by 1 ASC將工作)

@columns:可以選擇使用序號或列名

進一步發展,可以添加其他變量表名,例如。

CREATE PROCEDURE dbo.Sample_Procedure 
    @Orderby nvarchar(100) = 'Name Asc', 
    @Columns nvarchar(100) = '1,2,3,Name' 
AS 
DECLARE @SQLString nvarchar(500) 
DECLARE @UsedColumns nvarchar(500) 
DECLARE @X xml 

/* 
    Using string manipulation and covert to transform @Columns to xml, 
    so 1,2,3 becomes: <root><s>1</s><s>2</s><s>2</s></root> and then 
    converted to XML so we can select from it as if it was a table. 
    if you have SQL 2016 it's possible to replace it with STRING_SPLIT 
*/ 
SELECT @X = CONVERT(xml,' <root> <s>' + REPLACE(@Columns,',','</s> <s>') + '</s> </root> ') 


DECLARE @ColsTab as TABLE (Col nvarchar(100)) 
/*This part "shreds" the xml above into the variable table @ColsTab. 
    we need it for the `IN' operator later. 
*/ 
INSERT into @ColsTab (col) 
SELECT T.c.value('.','varchar(20)') FROM @X.nodes('/root/s') T(c) 


SET @UsedColumns = STUFF( (SELECT ',' + COLUMN_NAME 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME='tblStaging' 
     and (COLUMN_NAME in (Select Col from @ColsTab) 
      or ORDINAL_POSITION in (Select iif(IsNumeric(Col)=1,Col,Null) from @ColsTab) 
      ) 
       FOR XML PATH('')), 
      1, 1, '') 



SET @SQLString = 'Select '+ @UsedColumns +' 
from tblStaging 
order by '[email protected]by+' 
FOR XML RAW (''TRAN''), ROOT (''SEPA''), ELEMENTS'; 

EXECUTE sp_executesql @SQLString 

RETURN 

相同的查詢,這一次的動態查詢也設置輸出列的順序:

CREATE PROCEDURE dbo.Sample_Procedure2 
    @Orderby nvarchar(100) = 'Name Asc', 
    @Columns nvarchar(100) = '2,3,Name' 
AS 
DECLARE @SQLString nvarchar(500) 
DECLARE @UsedColumns nvarchar(500) 
DECLARE @X xml 

/* 
    Using string manipulation and covert to transform @Columns to xml, 
    so 1,2,3 becomes: <root><s>1</s><s>2</s><s>2</s></root> and then 
    converted to XML so we can select from it as if it was a table. 
    if you have SQL 2016 it's possible to replace it with STRING_SPLIT 
*/ 
SELECT @X = CONVERT(xml,' <root> <s>' + REPLACE(@Columns,',','</s> <s>') + '</s> </root> ') 


DECLARE @ColsTab as TABLE (Col nvarchar(100)) 
/*This part "shreds" the xml above into the variable table @ColsTab. 
    we need it for the `IN' operator later. 
*/ 
INSERT into @ColsTab (col) 
SELECT T.c.value('.','varchar(20)') FROM @X.nodes('/root/s') T(c) 


/* This version usues left join to assume the same order of 
    columns as specified in the input field @Columns 
    be mindful not to specify the same field twice 
*/ 
SET @UsedColumns = STUFF( (
    SELECT  ',' + i.COLUMN_NAME 
    FROM  @ColsTab as c 
    LEFT JOIN INFORMATION_SCHEMA.COLUMNS as i 
     ON  i.COLUMN_NAME = Col 
      OR ORDINAL_POSITION = iif(IsNumeric(Col)=1,Col,Null) 
    WHERE  TABLE_NAME='tblStaging' 
     AND  COLUMN_NAME is not null 
       FOR XML PATH('')), 
       1, 1, '') 



SET @SQLString = 'Select '+ @UsedColumns +' 
from tblStaging 
order by '[email protected]+' 
FOR XML RAW (''TRAN''), ROOT (''SEPA''), ELEMENTS'; 

EXECUTE sp_executesql @SQLString 

RETURN 
+0

嗨@UV,這真的很有幫助!我試着運行腳本,它確實使用'@ Columns'中指定的列完美地創建了XML。但是它似乎是按照它們在表模式中出現的順序排列的,而不是按@ @ Columns變量中指定的順序。例如。我設置了@ @Columns ='4,1,2,3',但XML結果仍然以1,2,3,4的順序出現。 「@ Orderby」變量被設置爲「1 Asc」。不知道我哪裏錯了。你能幫忙嗎? –

+0

另外,我可以理解代碼的一些部分,但不是所有的,例如。如何分配'@ X'或'@ UserColumns'。如果你能解釋這是如何工作的,這將是非常好的,所以我可以根據需要更改代碼,或者在需要時添加更多條件等。非常感謝您的幫助! –

+0

嗨Asher,'@ OrderBy'用於排序,請注意它直接用在查詢的Order By部分。我會添加一些評論給你的代碼:) Cheers - Yuval –