2009-03-04 36 views
0

在編寫TSQL存儲過程時,我發現自己希望集中/規範化代碼的某些部分。舉例來說,如果我有這樣的查詢:T-SQL全局/共享數據

SELECT * FROM SomeTable WHERE SomeColumn IN (2, 4, 8) 

對於這樣的情況下,我想提出(2,4,8)在一些地方的程序之外,我可以重複使用在其他一些查詢後 - 避免重複。有沒有內置的方法來做到這一點?真正整潔的是,如果我可以分解整個SQL代碼片段(如WHERE子句的一部分),並在其他查詢中重用這些代碼,但我懷疑這是可能的。

謝謝。

回答

2

我經常想要一個類似的東西,但具體不存在。這裏有幾件你可以做的。

選項1

我們所做的是使用用戶定義函數(UDF)收集可以稱之爲全局變量。

您可以在查詢中內聯UDF,這使得它非常有用。

假設您想要指定跨多個存儲過程使用的服務器名稱。複製該值不會得到最佳維護。相反,你可以這樣做:

select * from clientNodes where serverName = dbo.SOME_SERVER_NAME() 

選項2

這一個是比較明顯的,但值得指出的。將您的值保存在查找表中並通過ID引用它。 ID不會改變,但它所指的值可能會改變。使用樣品例如以上,但此選項:

Table: Servers 
Columns: ServerID, ServerName 

declare @serverName varchar(50) 
select @serverName = ServerName from Servers where ServerID = 1 

這是數據庫規範化的典型做法,但人不一定想這對於保持集中DB-邏輯數據的目的。

我希望有幫助! Ian

+0

+1 - 當我遇到這個問題時我會用UDF – annakata 2009-03-04 21:53:15

0

在SQL Server 2005中,您可以考慮使用表值函數。

例如爲:

SELECT ... FROM SomeTable INNER JOIN SomeFunction() F ON SomeTable.SomeColumn = F.Id 

... 

CREATE FUNCTION SomeFunction() 
RETURNS @IdTable TABLE (Id INT) 
AS 
RETURN 
(
    SELECT 2 Id 
    UNION ALL 
    SELECT 4 
    UNION ALL 
    SELECT 8 
) 

更常見的是,你可能想在值作爲參數傳遞給存儲過程。你可以做成逗號分隔的字符串。例如。

EXEC MyProcedure('2,4,8') 

... 

CREATE PROCEDURE MyProcedure 
(
    @IdString AS VARCHAR(MAX) 
) 
AS 
BEGIN 
    SELECT ... FROM SomeTable INNER JOIN SomeFunction(@IdString) F ON SomeTable.SomeColumn = F.Id 
END 

... 

CREATE FUNCTION dbo.SomeFunction 
(
    @IdString VARCHAR(MAX) 
) 
RETURNS @IdTable TABLE (Id INT) 
AS 
BEGIN 
    DECLARE @CommaIndex INT, @TotalLength INT, @StartIndex INT, @Id VARCHAR(10) 
    SET @TotalLength=LEN(@IdString) 
    SET @StartIndex = 1 

    WHILE @StartIndex <= @TotalLength 
    BEGIN 
     SET @CommaIndex = CHARINDEX(',', @IdString, @StartIndex) 
     IF @CommaIndex > 0 
     BEGIN 
      SET @Id = SUBSTRING(@IdString, @StartIndex, @[email protected]) 
      SET @StartIndex = @CommaIndex + 1 
     END 
     ELSE 
     BEGIN 
      Set @Id = SUBSTRING(@IdString, @StartIndex, @[email protected]+1) 
      SET @StartIndex = @TotalLength+1 
     END 
     INSERT INTO @IdTable 
     (Id) 
     VALUES 
     (CAST(@Id AS INT)) 
    END 

    RETURN 
END 
0

你通常會爲您創建試圖完成什麼VIEW

首先創建一個返回值SomeColumn功能2,4,8

create function fnSomeTableFilters() 
returns @Result table (ID int not null) 
as 

begin 
    insert @Result(ID) 
    select 2 
    union select 4 
    union select 8 

    return 
end 
GO 

現在創建一個觀點,即過濾2,4,8

create view vwFilteredSomeTable 
as 
select * from SomeTable where SomeColumn in (select ID from dbo.fnSomeTableFilters()) 

最後,您的查詢變得

SELECT * FROM vwFilteredSomeTable 

確保爲您的視圖提供有意義的名稱

e.g)我有一個視圖對查詢活動網站叫vwActiveSites作爲顧名思義

create view vwActiveSites 
as 
    select ... 
    from Sites S 
    where S.Active = 1 

的美在這裏的是,使用vwFilteredSomeTable您所有的疑問並不需要改變。如果你需要過濾不同的值,只需要fnSomeTableFilters需要更改

0

是的 - 使用表或視圖。 SomeColumn是IN(2,4,8)必須以某種方式對您的數據有意義,所以這樣建模。給它一個有意義的名字,你可以自己重用它或者加入其他查詢。爲什麼把它埋在UDF或其他類似的東西里?

例如,如果SomeColumn是國家和值( 'FL', 'GA', 'SC')爲您的南東部地區,然後,而不是傳播:

SELECT * FROM SomeTable WHERE State IN ('FL', 'GA', 'SC') 

周圍的一切,只是創建一個地區專欄,並完成它。

重複使用靜態WHERE子句是另一個表或屬性(又名概念)只是乞求出來。