#sql-server #tsql #stored-procedures #parameter-passing #table-valued-parameters
#sql-server #tsql #хранимые процедуры #передача параметров #табличные параметры
Вопрос:
У меня много таблиц, которым нужны скремблеры идентификаторов, поэтому:
CREATE PROCEDURE SP_generateUniqueID ( -- pass table here somehow -- )
AS
BEGIN
DECLARE @ID varchar(100) -- NEW ID.
DECLARE @isIDInUse tinyint -- BOOLEAN YES/NO.
SET @isIDInUse=1
WHILE(@isIDInUse=1) -- KEEP GENERATING TILL YOU FIND ONE:
BEGIN
SET @ID= dbo.generateID('aA1a1') -- GENERATES ID. doesn't matter how.
IF (@ID NOT IN (@passedTable)) -- DOES @ID EXIST ALREADY?
/*(SEARCHES THE PASSED TABLE! Which its size will be 1XN)*/
SET @isIDInUse=0 -- NO, YOU CAN USE.
END
RETURN @ID
END
Я не могу сделать так, чтобы передача существующей таблицы проходила гладко…
Я хочу иметь возможность вставлять любую таблицу, использующую идентификаторы.
Есть предложения?
Комментарии:
1. Есть несколько вариантов (CLR, динамический SQL). Но это может помочь, если вы объясните цель. С добавлением контекста у вас больше шансов получить правильное решение.
2. вы проверили табличный параметр?
3. Табличные параметры — это тупик — вы не можете просто передать таблицу, вы можете передать только табличную переменную.
4. Если вы пытаетесь сгенерировать уникальный идентификатор, почему бы вам не использовать UNIQUEIDENTIFIER с помощью NewId() или NewSequentialID() или ПОСЛЕДОВАТЕЛЬНОСТЬ. См msdn.microsoft.com/en-us/library/ms190348.aspx и msdn.microsoft.com/en-us/library/ff878091.aspx .
5. Здесь происходит ряд вещей, которые далеки от идеала. Сначала вы назвали свою процедуру с префиксом sp_ . Это не очень хорошая практика. sqlperformance.com/2012/10/t-sql-queries/sp_prefix Затем у вас есть цикл, генерирующий некоторую информацию. И внутри вашего цикла есть скалярная функция. Дополните это возможными проблемами параллелизма, и вся эта идея нуждается в переосмыслении.
Ответ №1:
Я бы посоветовал вам ДЕЙСТВИТЕЛЬНО внимательно изучить лучшие решения этой проблемы. Вы будете попадать в свою таблицу / индекс с каждой итерацией нового идентификатора, который вы генерируете. Что не так с автоинкрементным целочисленным значением:
create table IDs (ID int identity(1,1))
(кроме того, SQL Server имеет bit
типы данных для логических значений. Нет необходимости в вашем tinyint
)
Кроме того, единственный способ, которым, я думаю, вы можете сделать это по-своему, — это использовать динамический SQL. Используя приведенный ниже скрипт, вы должны увидеть, как вы можете передать свою schema.table
в хранимую процедуру и в рамках процедуры определить, что вы ID
должны быть вставлены в цикл проверки:
create table a(ID nvarchar(100)) insert into a values('1'),('2'),('3'),('4'),('5')
create table b(ID nvarchar(100)) insert into b values('6'),('7'),('8'),('9'),('10')
declare @Table nvarchar(100) = 'dbo.a'
declare @ID nvarchar(100) = '6'
declare @IDinUse bit = 0
declare @sql nvarchar(max) = 'if exists(select ID from ' @Table ' where ID = @ID) select @IDinUse = 1 else select @IDinUse = 0'
exec sp_executesql @sql, N'@ID nvarchar(100), @IDinUse bit output', @ID = @ID, @IDinUse = @IDinUse output
select @IDinUse as IDinUse
go
declare @Table nvarchar(100) = 'dbo.b'
declare @ID nvarchar(100) = '6'
declare @IDinUse bit = 0
declare @sql nvarchar(max) = 'if exists(select ID from ' @Table ' where ID = @ID) select @IDinUse = 1 else select @IDinUse = 0'
exec sp_executesql @sql, N'@ID nvarchar(100), @IDinUse bit output', @ID = @ID, @IDinUse = @IDinUse output
select @IDinUse as IDinUse