#c# #sql #sql-server #stored-procedures #dynamic-sql
Вопрос:
Я искал, как я могу параметризовать имена таблиц, и поэтому я нашел динамические sql-запросы. Я, наконец, сохранил процесс, но когда я его выполняю, он выдает ошибку «Не удалось выполнить преобразование при преобразовании значения varchar’ И ID =’ в тип данных int». Я понятия не имею, что происходит не так, когда я пытаюсь выполнить этот сохраненный процесс. Я чувствую, что это, должно быть, опечатка, но я не могу сказать. Сохраненный профи.
ОТРЕДАКТИРОВАНО, чтобы включить приведенное ниже предложение. По-прежнему не везет, если только я не делаю это неправильно.
-- =======================================================
-- Create Stored Procedure Template for Azure SQL Database
-- =======================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author, , Name>
-- Create Date: <Create Date, , >
-- Description: <Description, , >
-- =============================================
ALTER PROCEDURE [dbo].[sp_GetFormFieldCDC]
(
@formfieldId INT,
@C___operation INT,
@C___start_lsn binary(10),
@tablename NVarchar(255)
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
DECLARE @ActualTableName AS NVarchar(255)
SELECT @ActualTableName = QUOTENAME( TABLE_NAME )
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = @tablename
DECLARE @sql AS NVARCHAR(MAX)
SELECT @sql = 'SELECT * FROM ' @ActualTableName ' WHERE __$start_lsn =' CONVERT(NVARCHAR(255),@C___start_lsn) ' AND __$operation =' @C___operation ' AND ID =' @formfieldId ';'
-- Insert statements for procedure here
EXEC sp_executesql @SQL, N' @formfieldId INT,
@C___operation INT,
@C___start_lsn binary(10),
@tablename NVarchar(255)', @formfieldId ,
@C___operation,
@C___start_lsn,
@tablename
END
GO
Комментарии:
1. Используйте параметры,
sp_executesql
и этого не произойдет.2. Кроме того, правильно укажите ваши имена динамических объектов
QUOTENAME
; в противном случае это огромный недостаток безопасности.3. «Я искал, как я могу параметризовать имена таблиц, и поэтому я нашел динамические sql-запросы». Теперь у тебя две проблемы.
4. Наконец, не используйте
sp_
в качестве префикса, Microsoft зарезервировала его для особых случаев. Его использование сопряжено с высокой эффективностью и может привести к тому, что ваша процедура просто не сработает в один прекрасный день.
Ответ №1:
Вы должны передать параметры до конца в sp_executesql
. Не вводите их, если только это не имена объектов, в этом случае вам нужно QUOTENAME
.
Вы также можете использовать
OBJECT_ID
, чтобы проверить наличие таблицы и создать исключение, если такого объекта нет.
CREATE OR ALTER PROCEDURE [dbo].[GetFormFieldCDC]
(
@formfieldId INT,
@C___operation INT,
@C___start_lsn binary(10),
@schemaname sysname,
@tablename sysname
)
AS
SET NOCOUNT ON;
IF (OBJECT_ID(QUOTENAME(@schemaname) '.' QUOTENAME(@tablename)) IS NULL)
THROW 50000, 'Table not found', 0;
DECLARE @sql AS NVARCHAR(MAX) = '
SELECT *
FROM ' QUOTENAME(@schemaname) '.' QUOTENAME(@tablename) '
WHERE __$start_lsn = @C___start_lsn
AND __$operation = @C___operation
AND ID = @formfieldId;
';
EXEC sp_executesql @SQL,
N' @formfieldId INT,
@C___operation INT,
@C___start_lsn binary(10)',
@formfieldId = @formfieldId,
@C___operation = @C___operation,
@C___start_lsn = @C___start_lsn;
GO
Комментарии:
1. Получение той же ошибки после ее изменения на эту.
2. Это невозможно, этот код не выдаст ошибку
Conversion failed when converting the varchar value ' AND ID =' to data type int
, потому что здесь не происходит неявного преобразования. Какое фактическое сообщение об ошибке вы получаете?3. Моя ошибка — я использовал неправильный sp. Отлично работает, спасибо.