Одна проблема, которую я вижу (благодаря @GuidoG) заключается в том, что если @param1
или @param2
равны NULL
, то ваша @QRY
строка будет NULL
.
Вы можете заменить эти строки ...
SET @QRY = @QRY + ' DECLARE @param1 nvarchar(MAX) = ' + CHAR(39) + ISNULL(@param1, 'NULL') + CHAR(39) + ';'
SET @QRY = @QRY + ' DECLARE @param2 nvarchar(MAX) = ' + CHAR(39) + ISNULL(@param2, 'NULL') + CHAR(39) + ';'
Лично я все равно пропущу части параметров. Вы не избежите их, поэтому открыты для атак SQL-инъекций и / или неожиданных сбоев.
sp_executesql
позволяет избежать этих проблем ...
SET @QRY = @QRY + ' INSERT INTO tableName (column1, column2'
IF @param3 is not null
SET @QRY = @QRY + ', column3'
IF @param4 is not null
SET @QRY = @QRY + ', column4'
IF @param5 is not null
SET @QRY = @QRY + ', column5'
SET @QRY = @QRY + ') VALUES '
SET @QRY = @QRY + ' (@param1, @param2 '
IF @param3 is not null
SET @QRY = @QRY + ', @param3'
IF @param4 is not null
SET @QRY = @QRY + ', @param4'
IF @param5 is not null
SET @QRY = @QRY + ', @param5'
SET @QRY = @QRY + ')'
EXEC sp_executesql
@QRY,
N'@param1 NVARCHAR(MAX),
@param2 NVARCHAR(MAX),
@param3 NVARCHAR(MAX),
@param4 NVARCHAR(MAX),
@param5 NVARCHAR(MAX)',
@param1,
@param2,
@param3,
@param4,
@param5
(Даже если вы передаете все 5 параметров, только те, которые вас интересуют, используются в INSERT
, а передача их в качестве параметров предотвращает атаки SQL-инъекций или необходимость экранирования специальных символов и т. Д. и т. д. О, и вы никогда не рискуете объединить NULL
.)
EDIT:
Я также оглянулся, чтобы посмотреть, есть ли лучший способ выбрать значения по умолчанию для столбцов. Хотя я не мог найти ничего «лучшего», есть «другой» подход ...
INSERT INTO
tableName(
column1,
column2,
column3,
column4,
column5
)
SELECT
@param1,
@param2,
ISNULL(@param3, MAX(CASE WHEN COLUMN_NAME = 'column3' THEN COLUMN_DEFAULT END)),
ISNULL(@param4, MAX(CASE WHEN COLUMN_NAME = 'column4' THEN COLUMN_DEFAULT END)),
ISNULL(@param5, MAX(CASE WHEN COLUMN_NAME = 'column5' THEN COLUMN_DEFAULT END))
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = 'dbo' -- or whatever it really is in your case
AND TABLE_NAME = 'tableName'
;
Для этого вообще не нужен динамический SQL. Но я не уверен, что это лучше, чем Dynamic SQL.
EDIT2:
ОН !!!
Ваш код показывает ROLLBACK
в обработке ошибок, что означает, что в коде, который вы нам не показываете, BEGIN TRANSACTION
?
У вас на самом деле есть COMMIT TRANSACTION
где-нибудь ???