TSQL评估连接字符串

时间:2018-06-12 20:21:01

标签: sql-server tsql sp-executesql

我有一个带有如下构造字符串的表。有没有办法执行每个构造的字符串并将结果存储在行中的另一个字段中?

    ROW 1 'SELECT NAME FROM  ZC_ETHNIC_GROUP WHERE INTERNAL_ID = 4'
    ROW 2 'SELECT NAME FROM  ZC_LANGUAGE WHERE INTERNAL_ID = 1'
    ROW 3 'SELECT NAME FROM  ZC_PATIENT_RACE WHERE INTERNAL_ID = 8'
    ROW 4 'SELECT NAME FROM  ZC_SEX WHERE INTERNAL_ID = 1'

2 个答案:

答案 0 :(得分:0)

我就是这样做的:

DECLARE @PendingQuery TABLE
(
    ID INT NOT NULL IDENTITY(1, 1)
    ,SqlQuery NVARCHAR(MAX) NOT NULL
    ,HasBeenEvaluated BIT NOT NULL DEFAULT(0)
    ,IsEvaluationSuccess BIT NULL
    ,FailureMessage VARCHAR(255) NULL
    ,QueryResult NVARCHAR(MAX) NULL
)
--create mock data
INSERT INTO @PendingQuery(SqlQuery)
SELECT 'SELECT 1'
UNION ALL
SELECT 'SELECT NULL'
UNION ALL
SELECT 'SELECT 1=garbage'--sample invalid query with an error
--begin algorithm
DECLARE
    @ID INT
    ,@Query NVARCHAR(MAX)
    ,@IsEvaluationSuccess BIT
    ,@Error NVARCHAR(4000)
    ,@QueryResult NVARCHAR(MAX)
DECLARE EvaluationCursor CURSOR LOCAL STATIC FOR
    SELECT ID, SqlQuery
    FROM @PendingQuery
    WHERE HasBeenEvaluated = 0
OPEN EvaluationCursor
FETCH NEXT FROM EvaluationCursor INTO
    @ID
    ,@Query
WHILE @@FETCH_STATUS = 0
BEGIN
    SELECT--reset iteration variables
         @QueryResult = NULL
        ,@Error = NULL
        ,@Query = N'SELECT @QueryResult = (' + @Query + N')'

    BEGIN TRY
    BEGIN TRANSACTION
        EXEC sp_executesql
            @Query
            ,N'@QueryResult NVARCHAR(MAX) OUTPUT'
            ,@QueryResult=@QueryResult OUTPUT
        ROLLBACK--disallow data alteration
        SET @IsEvaluationSuccess = 1
    END TRY
    BEGIN CATCH
        IF @@TRANCOUNT > 0 ROLLBACK--orphaned transaction needs to be rolled back first
        SELECT
             @IsEvaluationSuccess = 0
            ,@Error = ERROR_MESSAGE()--you might want more info such as the error line
    END CATCH

    UPDATE @PendingQuery
    SET
        HasBeenEvaluated = 1
        ,IsEvaluationSuccess = @IsEvaluationSuccess
        ,FailureMessage = @Error
        ,QueryResult = @QueryResult
    WHERE ID = @ID

    FETCH NEXT FROM EvaluationCursor INTO
        @ID
        ,@Query
END
CLOSE EvaluationCursor
DEALLOCATE EvaluationCursor
--check results
SELECT * FROM @PendingQuery

对于三个样本请求,结果如下:

enter image description here

P.S。我确实希望这些查询不是来自unsanitized user data

P.P.S。我没有看到任何基于集合的解决方案。似乎需要游标或自定义循环。

答案 1 :(得分:0)

declare @queries table(id int, query varchar(50), result varchar(50))

insert into @queries(id, query)
select 1, 'select 1'
union select 2, 'select 2'
union select 3, 'select 3'
union select 4, 'select 4'

declare @id int
set @id = -1

declare @query nvarchar(100)

DECLARE @tabOut AS TABLE (outVal varchar(100)) 


while(@id is not null) begin

    set @id = null
    select top 1
        @id = id,
        @query = query
    from @queries
    where result is null

    delete from @tabOut

    if (@id is not null) begin
        INSERT into @tabOut EXECUTE sp_executesql @query

        update @queries
        set result = (select top 1 outVal from @tabOut)
        where id = @id
    end;
end;

select * from @queries

只需将“选择1”,“选择2”...替换为您的查询。