2012-02-24 61 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