使用动态SQL访问存储过程参数

时间:2010-10-22 23:06:44

标签: sql-server tsql

我有一个由数据收集系统调用的存储过程。

该过程有许多参数可用于收集的数据。

我正在使用INFORMATION_SCHEMA将参数列表拉入临时表

    SELECT substring(PARAMETER_NAME , 2 , len(PARAMETER_NAME ) - 1) 'SpParam', PARAMETER_NAME, DATA_TYPE
    INTO #tempParam
    FROM INFORMATION_SCHEMA.PARAMETERS
    WHERE SPECIFIC_NAME='InsertB2ChamberData'   

从那里我可以在我的标签列表表中插入任何缺少的数据标签名称

    INSERT INTO ToolTag
    SELECT @ToolID, @ToolTagTypeID, SpParam, 'Default Description', GETDATE()
    FROM #tempParam
    WHERE spParam NOT IN (SELECT ToolTagName FROM ToolTag WHERE ToolID = @ToolID)

到目前为止一切顺利,现在我想使用ToolTag和临时表列表来插入每个参数的数据。初始我虽然有些动态SQL可以解决问题。

    DECLARE tag CURSOR FOR 
    SELECT t.ToolTagID, p.PARAMETER_NAME, p.DATA_TYPE
    FROM ToolTag t
        JOIN #tempParam p
            ON t.ToolTagName = p.SpParam

    OPEN tag

    FETCH NEXT FROM tag INTO @TagID, @Parameter, @DataType

    WHILE @@FETCH_STATUS = 0
    BEGIN

        SELECT @Cindex = CHARINDEX('char', @DataType)
        IF @Cindex  0
        begin

            SELECT @sql = 
            N'INSERT INTO ToolTagData VALUES('+convert(varchar(10),@TagID)+', '+convert(varchar(10),@ToolDataEventID)+', '+ @Parameter +', 0)'
        end
        else
        begin
            SELECT @sql = 
            N'INSERT INTO ToolTagData VALUES('+convert(varchar(10),@TagID)+', '+convert(varchar(10),@ToolDataEventID)+', CONVERT(varchar(255),'+@Parameter +'), '+convert(varchar(50),@Parameter)+')'

        end

        EXEC(@sql)

        FETCH NEXT FROM tag INTO @TagID, @Parameter, @DataType
    END

    CLOSE tag
    DEALLOCATE tag

当然上面的内容不起作用,因为@sql语句的结尾是这样的:

INSERT INTO ToolTagData VALUES(315,50,@ ShutterPosition,0)

与@ShutterPosition参数值相对。我被困在这里,我可以对每个名字都有某种蛮力,但我希望能够是抽象的并且可以重新使用其他程序。

那么有什么方法可以解决这个问题,还是我用这种方法咆哮错误的树?

修改 我的架构看起来像这样: alt text

目标是为每个存储过程参数在ToolTagData Data中插入一条记录。 ToolTag的关键是存储过程参数的名称。

希望只需在程序中添加一个新参数即可将标签添加到ToolTag表中。

我受限于第三方数据采集程序可以做什么,所以这是一个尝试抽象的过程。

2 个答案:

答案 0 :(得分:1)

而不是EXEC,请使用sp_ExecuteSQL

然后你可以这样做:

DECLARE
    @sql nvarchar(max),
    @ParamDef nvarchar(1000)


SET @ParamDef = N'@param1 int,
    @param2 int'

EXECUTE dbo.sp_ExecuteSQL @sql, @ParamDef,
    @param1 = @param1,
    @param2 = @param2

答案 1 :(得分:0)

最后我决定使用CLR存储过程来实现这个目的:

var tags = new
                                           {
                                                   @Tag1,
                                                   @Tag2,
                                                   ...
                                                   @LastTag};

             using (var conn =
                      new SqlConnection("context connection = true"))
             {
                      conn.Open();
                      var cmd = new SqlCommand
                                                  {
                                                           Connection = conn,
                                                           CommandText =
                                                                    "INSERT INTO TagGroupData SELECT TagGroupID , GETDATE() FROM TagGroup WHERE TagGroupName = 'L1Data' SELECT SCOPE_IDENTITY()"
                                                  };

                      var tagGroupDataId = cmd.ExecuteScalar();

                      cmd.CommandText = "";


                      cmd.Parameters.Add("@Data", SqlDbType.Float);
                      cmd.Parameters.Add("@Name", SqlDbType.VarChar, 100);
                      cmd.Parameters.Add("@tg", SqlDbType.Int);

                      cmd.Parameters[2].Value = tagGroupDataId;

                      cmd.CommandText =
                               "INSERT INTO ToolTagData SELECT t.ToolTagID, CONVERT(varchar(255),@Data), @Data, @tg, GETDATE() FROM ToolTag t WHERE t.ToolTagName = @Name";

                      foreach (PropertyInfo pi in tags.GetType().GetProperties())
                      {
                               cmd.Parameters[1].Value = pi.Name;
                               cmd.Parameters[0].Value = pi.GetValue(tags, null);

                               cmd.ExecuteScalar();
                      }