Общая вставка хранится в процессе: ошибка во время выполнения - PullRequest
1 голос
/ 19 января 2009

Следующий код генерирует первичный ключ для новой записи, которую нужно вставить, и вставляет запись в таблицу, чье имя и значения, которые нужно вставить, задаются в качестве параметров хранимой процедуры. Я получаю ошибку во время выполнения. Я использую Visual Studio 2005 для работы с SQL Server 2005 Express Edition

ALTER PROCEDURE spGenericInsert

(
    @insValueStr nvarchar(300), 
    @tblName nvarchar(10) 
)


AS

DECLARE @sql nvarchar(400)
DECLARE @params nvarchar(200)
DECLARE @insPrimaryKey nvarchar(10)
DECLARE @rowCountVal integer
DECLARE @prefix nvarchar(5)

--following gets the rowcount of the table--
SELECT @rowCountVal = ISNULL(SUM(spart.rows), 0)
    FROM sys.partitions spart 
    WHERE spart.object_id = object_id(@tblName) AND spart.index_id < 2

SET @rowCountVal = @rowCountVal+1




--Following Creates the Primary Key--
IF @tblName = 'DEFECT_LOG' 
    SET @prefix='DEF_'
ELSE IF @tblName='INV_Allocation_DB'
    SET @prefix='INV_'
ELSE IF @tblName='REQ_Master_DB'
    SET @prefix='REQ_'
ELSE IF @tblName='SW_Master_DB'
    SET @prefix='SWI_'
ELSE IF @tblName='HW_Master_DB'
    SET @prefix='HWI_'  


SET @insPrimaryKey= @prefix + RIGHT(replicate('0',5)+ convert(varchar(5),@rowCountVal),5) -- returns somethin like 'DEF_00005'


-- Following is for inserting into the table --

SELECT @sql =   N' INSERT INTO @tableName VALUES ' +
        N' ( @PrimaryKey , @ValueStr )'

SELECT @params = N'@tableName nvarchar(10), ' +
                    N'@PrimaryKey nvarchar(10), ' +
                    N'@ValueStr  nvarchar(300)'

EXEC sp_executesql @sql, @params, @tableName=@tblName, @PrimaryKey=@insPrimaryKey, @ValueStr=@insValueStr

Выходное сообщение:

Running [dbo].[spGenericInsert] ( @insValueStr = 2,"Hi",1/1/1987, @tblName = DEFECT_LOG ).

Must declare the table variable "@tableName".

No rows affected.

(0 row(s) returned)

@RETURN_VALUE = 0

Finished running [dbo].[spGenericInsert].

Ответы [ 3 ]

4 голосов
/ 19 января 2009

Вам нужно будет объединить имя таблицы непосредственно в строку, так как это не может быть параметризовано:

SELECT @sql =   N' INSERT INTO [' + @tblName + '] VALUES ' +
            N' ( @PrimaryKey , @ValueStr )'

SELECT @params = N'@PrimaryKey nvarchar(10), ' +
                N'@ValueStr  nvarchar(300)'

Чтобы предотвратить инъекционные атаки, вы должны занести в белый список это имя таблицы. Это также не является надежным, если в таблице есть другие необнуляемые столбцы и т. Д.

примечание: Лично я не думаю, что это хорошее использование TSQL; может быть более целесообразно создать команду на клиенте (C # или что-то еще) и выполнить ее как параметризованную команду. Существуют варианты использования для динамического SQL, но я не уверен, что это хороший пример.

Еще лучше, используйте предпочитаемый инструмент ORM (LINQ-to-SQL, NHibernate, LLBLGen, Entity Framework и т. Д.), Чтобы сделать все это за вас, и сконцентрируйтесь на фактической проблемной области.

0 голосов
/ 19 января 2009

Согласитесь с Марком - в целом это крайне плохая идея. Общие вставки / обновления или удаления в конечном итоге вызывают проблемы для базы данных.

Другой момент заключается в том, что у этого процесса будут проблемы, когда два пользователя одновременно будут работать с одной и той же таблицей, когда они попытаются вставить один и тот же первичный ключ.

0 голосов
/ 19 января 2009

Белый список, по сути, означает, что передаваемая таблица является допустимой таблицей, в которую вы хотите, чтобы она могла быть вставлена. Скажем только для аргументов, что имя таблицы предоставлено пользователем, пользователь может начать вставлять записи в системные таблицы.

Вы можете выполнить проверку белого списка, отразив имя таблицы таблицы sysobjects:

выбор * из системных объектов, где name = @ tblname и xType = 'U'

Однако, как предположил Марк, это нецелесообразное использование TSQL, и вам лучше обрабатывать его на уровне приложений как парализованный запрос.

...