2012-02-24 59 views
0

我有一個存儲過程,此時將返回一個projectID列表。我想擴展它以返回一些額外的信息來確定特定用戶是否有權訪問此項目。替代動態SQL函數

要確定用戶是否具有訪問權限,我需要在名爲'Project_XXX'的表中查找用戶,其中XXX是projectID。是的,這是令人震驚的數據庫設計,但遺憾的是我無能爲力。我的第一反應是,我可以用一個函數作爲這樣的:

SELECT ProjectID WHERE [criteria] AND myfunc(ProjectID, @username)=1 

但是,由於查找需要運行它告訴我,我不能這樣做動態SQL。

這使我可以選擇將我的邏輯放入存儲過程,但是我的選擇語法並不簡單。

我能想到的方法是運行select來獲取projectID列表,然後在該表上運行一個指針來調用我的存儲過程,但是我停止思考,因爲它看起來太複雜了......

那麼有沒有什麼辦法可以做到我想要的類似簡單的語法以上?有沒有辦法讓用戶函數返回基於動態SQL?如上所述,有沒有一種很好的方式來使用存儲過程?我確信我錯過了一些明顯的東西 - 儘管我很少需要做任何與SQL相關的事情。 ;-)

我還要重申,我知道深層的問題是愚蠢的個別項目表,但這不是一朝一夕所能改變。

回答

2

一種選擇是從所有project_xxx表創建一個視圖。喜歡的東西:

CREATE VIEW SecurityTable 
AS 
SELECT 'Project_1', User, HasAccess 
FROM Project_1 
UNION 
SELECT 'Project_2', User, HasAccess 
FROM Project_2 
UNION 
SELECT 'Project_3', User, HasAccess 
FROM Project_3 
etc... 

然後,你可以簡單地查詢您的看法,就像數據庫已經擺在首位;-)

SELECT ProjectID, User 
FROM SecurityTable 
WHERE [criteria] 
AND HasAccess=1 


正確設計爲你的國家,你會經常添加新的項目表,我建議你每天早上可以有一個安全表填充動態查詢。例如:

CREATE TABLE Project_1 (
    Usr varchar(20), 
    HasAccess bit) 
GO 
CREATE TABLE Project_2 (
    Usr varchar(20), 
    HasAccess bit) 
GO 
CREATE TABLE SecurityTable (
    Usr varchar(20), 
    HasAccess bit) 
GO 


INSERT INTO Project_1 (Usr, HasAccess) VALUES ('Kermit', 1) 
INSERT INTO Project_1 (Usr, HasAccess) VALUES ('MissPiggy', 1) 
INSERT INTO Project_2 (Usr, HasAccess) VALUES ('Beaker', 1) 
INSERT INTO Project_2 (Usr, HasAccess) VALUES ('TheCount', 0) 
GO 

Create Procedure LoadSecurityTable 
AS 
    DELETE * FROM SecurityTable 

    EXEC sp_MSForEachTable 
     @command1 = 'INSERT INTO SecurityTable (Usr, HasAccess) SELECT Usr, HasAccess FROM ?', 
     @whereand = 'AND o.name LIKE ''Project_%''' 
GO 

EXEC LoadSecurityTable 
SELECT * FROM SecurityTable 
+0

我曾經考慮過這個問題,但我懷疑每次創建新項目時都必須將項目添加到視圖中來解決問題。除非有一種方法可以用某種動態sql創建視圖,所以我不需要更新它...? :) – Chris 2012-02-24 12:03:01

+0

我已經更新了我的答案。奇怪的是我想把'TRUNCATE TABLE'而不是'DELETE * FROM',但StackOverflow不會讓我! – 2012-02-24 12:41:38

+0

sp_MSForEachTable的新部分看起來很有前途,我希望我可以給你另外一個+1。;-) – Chris 2012-02-24 13:46:03

1

如您所知,您無法運行動態SQL或從函數內調用存儲過程。

有一個非常醜陋的變通方法,需要調用使用xp_cmdshell你的函數中的批處理腳本(.bat)的形式,並在批處理腳本中使用sp_executesql執行動態SQL。

但是,爲了簡單起見,我會使用RB的視圖解決方案!

+0

是的,這聽起來像一個解決方法,在某些時候將成爲PITA。 :) – Chris 2012-02-24 12:09:18