У меня есть следующее, которое возвращает строку, созданную EXEC в выходных данных при непосредственном запуске хранимой процедуры, но мне нужно передать эту строку обратно в вызывающую хранимую процедуру.
Эта хранимая процедура будет вызываться из основного цикла другой хранимой процедуры, и мне нужно, чтобы текст, созданный EXEC, сохранялся в переменной вызывающей процедуры.
Я раньше использовал команду EXEC sp_executesql, но не знаю, применимо ли это здесь.
Выход:
target.JOBID = source.JOBID And target.stackid = source.stackid And target.testtypeid = source.testtypeid And target.sampledparameter = source.sampledparameter And
Completion time: 2024-06-26T16:42:29.4295301+01:00
Это хранимая процедура, которая мне нужна для возврата вывода EXEC:
ALTER PROCEDURE [dbo].[GetLinkCriteria]
@TableName nvarchar(max)
AS
BEGIN
SET NOCOUNT ON
DECLARE @sql nvarchar(max);
SET @sql = '
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''JOBID'' )
BEGIN SET @linkcriteria = ''target.JOBID = source.JOBID And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''stackid'')
BEGIN SET @linkcriteria += ''target.stackid = source.stackid And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''testtypeid'')
BEGIN SET @linkcriteria += ''target.testtypeid = source.testtypeid And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''colid'')
BEGIN SET @linkcriteria += ''target.colid = source.colid And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''runid'')
BEGIN SET @linkcriteria += ''target.runid = source.runid And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''lineid'')
BEGIN SET @linkcriteria += ''target.lineid = source.lineid And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''component'')
BEGIN SET @linkcriteria += ''target.component = source.component And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''sampledparameter'')
BEGIN SET @linkcriteria += ''target.sampledparameter = source.sampledparameter And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''parameter'')
BEGIN SET @linkcriteria += ''target.parameter = source.parameter And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''filename'')
BEGIN SET @linkcriteria += ''target.filename = source.filename And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''runtype'')
BEGIN SET @linkcriteria += ''target.runtype = source.runtype And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''parentmetalparameter'')
BEGIN SET @linkcriteria += ''target.parentmetalparameter = source.parentmetalparameter And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''metal'')
BEGIN SET @linkcriteria += ''target.metal = source.metal And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''gassampled'')
BEGIN SET @linkcriteria += ''target.gassampled = source.gassampled And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''sampledgas'')
BEGIN SET @linkcriteria += ''target.sampledgas = source.sampledgas And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''purpose'')
BEGIN SET @linkcriteria += ''target.purpose = source.purpose And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''' + @tableName + ''' AND COLUMN_NAME = ''isblank'')
BEGIN SET @linkcriteria += ''target.isblank = source.isblank And '' END
PRINT @linkcriteria;
';
EXEC ('DECLARE @linkcriteria nvarchar(max);' + @Sql)
END
Я создаю список назначений динамических связей таблиц, которые будут помещены в команду MERGE, которая используется для получения необработанной обновленной даты из программы C# и ее объединения с существующей базой данных. Это необходимо сделать таким образом, поскольку нет полей индекса уникального идентификатора. sql-инъекция на данный момент не является проблемой, поскольку она еще далека от реализации. Если это когда-нибудь сработает, это будет привязано когда-нибудь в будущем!





Как возврат значения вызывающей процедуре, так и отказ от SQL-инъекции сводятся к использованию выходных параметров как в хранимой процедуре, так и в sp_executesql. Попробуйте что-то вроде этого:
CREATE OR ALTER PROCEDURE [dbo].[GetLinkCriteria]
@TableName nvarchar(max),
@rv nvarchar(max) output
AS
/*
declare @rv nvarchar(max)
exec GetLinkCriteria @tablename='foo', @rv=@rv output
print @rv
*/
BEGIN
SET NOCOUNT ON
DECLARE @sql nvarchar(max);
SET @sql = '
DECLARE @linkcriteria nvarchar(max) = '''';
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''JOBID'' )
BEGIN SET @linkcriteria = ''target.JOBID = source.JOBID And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''stackid'')
BEGIN SET @linkcriteria += ''target.stackid = source.stackid And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''testtypeid'')
BEGIN SET @linkcriteria += ''target.testtypeid = source.testtypeid And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''colid'')
BEGIN SET @linkcriteria += ''target.colid = source.colid And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''runid'')
BEGIN SET @linkcriteria += ''target.runid = source.runid And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''lineid'')
BEGIN SET @linkcriteria += ''target.lineid = source.lineid And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''component'')
BEGIN SET @linkcriteria += ''target.component = source.component And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''sampledparameter'')
BEGIN SET @linkcriteria += ''target.sampledparameter = source.sampledparameter And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''parameter'')
BEGIN SET @linkcriteria += ''target.parameter = source.parameter And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''filename'')
BEGIN SET @linkcriteria += ''target.filename = source.filename And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''runtype'')
BEGIN SET @linkcriteria += ''target.runtype = source.runtype And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''parentmetalparameter'')
BEGIN SET @linkcriteria += ''target.parentmetalparameter = source.parentmetalparameter And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''metal'')
BEGIN SET @linkcriteria += ''target.metal = source.metal And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''gassampled'')
BEGIN SET @linkcriteria += ''target.gassampled = source.gassampled And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''sampledgas'')
BEGIN SET @linkcriteria += ''target.sampledgas = source.sampledgas And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''purpose'')
BEGIN SET @linkcriteria += ''target.purpose = source.purpose And '' END
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = ''isblank'')
BEGIN SET @linkcriteria += ''target.isblank = source.isblank And '' END
--print(@linkcriteria)
set @rv = @linkcriteria;
';
--print @sql
EXEC sp_executesql @sql, N'@tableName nvarchar(max), @rv nvarchar(max) output', @tableName=@tableName, @rv = @rv output
END
Я внес эти изменения в процедуру GetLinkCriteria, но когда я запускаю ее напрямую, она по-прежнему отображает текст при запуске команды «exec GetLinkCriteria @tablename='StackDetails', @rv=@rv output» и ничего не показывает для «PRINT». @rv". Это означает, что когда я пытаюсь вызвать это из основной процедуры, оно сохраняет содержимое текста EXEC, а не предполагаемый результат.
Хотя текст, внесенный в основную процедуру, соответствует моим ожиданиям.
Я получил это на основе того, что вы сказали, спасибо.
Я исправил это на основе того, что предоставил Дэвид. Мне просто нужно было установить возвращаемое значение «rv» в мою переменную @linkcriteria. и удалите оператор PRINT, который использовался для тестирования.
Например.
SET @rv = @linkcriteria
--PRINT @linkcriteria;
';
EXEC sp_executesql @sql, N'@LinkTableName nvarchar(max), @rv nvarchar(max) output', @LinkTableName=@LinkTableName, @rv=@rv output
Непонятно, чего вы здесь пытаетесь достичь, но будьте осторожны: эта процедура открыта для SQL-инъекций.