创建可以使用不同表的存储过程

MrT*_*lly 3 t-sql stored-procedures view

我需要对我的数据库中具有相同结构的许多表使用相同的存储过程.这是从客户加载的数据,具有一个表/客户,并且数据需要计算/检查在加载到我们的DataWarehouse之前运行.

到目前为止,这些是我发现的选项和问题,我正在寻找更好的模式/方法.

  1. 创建一个指向我要处理的表的视图,然后SP与该视图对话.这很好用(特别是一旦我找到了如何根据列自动创建视图).但是视图一次只能用于一个表,从而迫使系统一次处理一个客户.

  2. 在每个SP中使用动态sql - 使SP更难以读取/调试,并且由于这些原因已被排除

  3. 在所有表中创建一个分区视图,然后使用一个paramatised表函数返回我们感兴趣的数据 - 啊然后我无法更新数据,因为该函数返回一个只能用于select的表

  4. 在函数内部使用动态sql(无法完成)来创建视图(也无法完成)....放弃
  5. 在SP中使用动态sql创建一个覆盖目标表的临时表,但是临时表只存在于运行动态sql的会话中,而不是运行SP的"父"会话...放弃
  6. 使用动态SQL创建全局临时表以避免范围问题5,然后针对全局临时表运行SP.仍然遇到单一客户问题.
  7. 在事务中以1为单位创建视图,然后运行所有SP然后提交 - 对一个用户工作正常,但现在阻止任何其他用户尝试创建同名的新视图
  8. 使用临时视图...不能在T/Sql中
  9. 将所有代码移动到.Net - 但我们遇到环境问题,其中tsql更容易托管/运行

我知道我不是唯一有这个问题的人,请各位好人解决它,请帮忙.

Rod*_*igo 11

也许你的方法是错误的,我会在一段时间内深入细节,但似乎你的问题可以用SSIS解决

- 更新的答案:

首先,大局:

动态处理表的最经济的方法是使用脚本而不是存储过程.如果要随机选择表访问,您肯定不会使用存储过程的任何性能优势,即执行计划.可以使用占位符在运行时将SQL脚本轻松升级为指向一个表,并在执行前替换它.

可以从文件系统,变量,表中的文本列等加载脚本.加载过程包括将脚本内容读取到字符串变量.此步骤发生一次.

下一步是准备阶段.将对要处理的每个表执行此步骤.此步骤的主要业务是使用正在处理的当前表替换表占位符.也可以设置参数值,就像您可能需要传递到已编写的sp中的任何参数一样.

最后一步是执行脚本.由于已经加载到变量中并且占位符设置为当前表名,因此可以使用sql变量作为输入安全地调用ExecuteSQLTask.当然,这个过程适用于您要处理的每个表.

好.现在让我们看看这个在行动.

这是一个示例数据库模型:

CREATE TABLE [dbo].[t_n](
  [id] [int] IDENTITY(1,1) NOT NULL,
  [name] [varchar](50) NOT NULL,
  [start] [datetime] NULL,
  CONSTRAINT [PK_t_n] PRIMARY KEY CLUSTERED ([id] ASC)
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)

其中t_n表示任何表(t_1,t_2,t_3等).

这是您当前的存储过程:

CREATE PROCEDURE SpProcessT_n 
AS
BEGIN
    SET NOCOUNT ON;
    SELECT * FROM [t1]; 
END
GO
Run Code Online (Sandbox Code Playgroud)

现在,将此存储过程转换为Sql脚本,放置占位符而不是表名

    SET NOCOUNT ON;
    SELECT * FROM [$table_name];
Run Code Online (Sandbox Code Playgroud)

我选择将其保存在文件系统的.sql文件中,以使POC尽可能简单.

接下来,创建一个这样的SSIS包:

基本SSIS包

这些是我选择设置循环的设置: 在此输入图像描述

这是你可以将表名分配给一个名为_table_name_的变量的方法 在此输入图像描述

这是脚本任务的设置,在这里您发现变量_table_name_具有只读访问权限,而名为SqlExec的新变量具有读/写访问权限:

在此输入图像描述

这是它的主要功能:

    public void Main()
    {
        String Table_Name = Dts.Variables["table_name"].Value.ToString();
        String SqlScript;
        Regex reg = new Regex(@"\$table_name", RegexOptions.Compiled);
        using (var f = File.OpenText(@"c:\sqlscript.sql")) {
            SqlScript = f.ReadToEnd();
            f.Close();
        }
        SqlScript = reg.Replace(SqlScript, Table_Name);
        Dts.Variables["SqlExec"].Value = SqlScript;
        Dts.TaskResult = (int)ScriptResults.Success;
    }
Run Code Online (Sandbox Code Playgroud)

您可以注意到Dts Variable SqlExec包含将要执行的sql脚本.现在,您可以在ExecuteSqlTask​​中设置以下选项:

在此输入图像描述

在MSSQL 2008中成功测试过,如果在脚本文件中放入一个插入,您会注意到每个表中的新行.

希望这可以帮助!