Вот как я бы это сделал:
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
Для трех примеров запросов это результат:
PS I действительно надеюсь, что эти запросы не сформированы из неанизированных пользовательских данных !
PPS Я не вижу никакого решения этой проблемы на основе множеств.Курсор или пользовательский цикл кажутся необходимыми.