SQL Server: обходной путь для сохраненной входной таблицы Proc - PullRequest
0 голосов
/ 20 января 2011

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

create proc insertNewTask (@taskDesc varchar(100), @sTime datetime, @eTime datetime, @items table(itemID int))
as
 begin
  declare @newTask table(newID int)
  insert into tasks(description, sTimeUTC, eTimeUTC)
  output inserted.ID into @newTask
  values(@taskDesc, @sTime, @eTime)

  insert into taskItems(taskID, itemID)
  select newID, itemID
  from @newTask cross join @items
 end

Как уже говорилось, вышеприведенный код выиграл 't работает из-за ввода табличных переменных, @items (я полагаю, прежде всего, из-за проблем с переменной областью).Итак, есть ли хорошие обходные пути к этому?

Оригинальный вопрос
У меня есть три таблицы:

CREATE TABLE items
(
  ID          int PRIMARY KEY,
  name        varchar(20),
  description varchar(100)
)

CREATE TABLE tasks
(
  ID          int identity(1,1) PRIMARY KEY,
  description varchar(100),
  sTimeUTC    datetime,
  eTimeUTC    datetime
)

CREATE TABLE taskItems
(
  taskID      int,
  itemID      int,
  CONSTRAINT fk_taskItems_taskID FOREIGN KEY (taskID) on tasks(ID),
  CONSTRAINT fk_taskItems_itemID FOREIGN KEY (itemID) on items(ID)
)

С некоторыми начальными данными элемента:

insert into items (ID, name, description)
select 1, 'nails', 'Short piece of metal, with one flat side and one pointed side' union
select 2, 'hammer', 'Can be used to hit things, like nails' union
select 3, 'screws', 'I''m already tired of writing descriptions for simple tools' union
select 4, 'screwdriver', 'If you can''t tell already, this is all fake data' union
select 5, 'AHHHHHH', 'just for good measure'

И у меня есть код для создания новой задачи:

declare @taskDes varchar(100), @sTime datetime, @eTime datetime
select @taskDes = 'Assemble a bird house',
    @sTime = '2011-01-05 12:00', @eTime = '2011-01-05 14:00'

declare @usedItems table(itemID int)
insert into @usedItems(itemID)
select 1 union
select 2


declare @newTask table(taskID int)
insert into tasks(description, sTimeUTC, eTimeUTC)
output inserted.ID into @newTask
values(@taskDes, @sTime, @eTime)

insert into taskItems(taskID, itemID)
select taskID, itemID
from @newTask
    cross join @usedItems

Теперь я хочу упростить / упростить создание новых задач.Моей первой мыслью было использование хранимой процедуры, но переменные таблицы нельзя использовать в качестве входных данных, поэтому она не будет работать.Я думаю, что я могу сделать это с представлением с триггером вставки, но я не уверен ... Это мой лучший (или единственный) вариант?

1 Ответ

0 голосов
/ 05 марта 2011

Мне очень повезло, используя XML для передачи данных в процедуры. Вы можете использовать OPENXML (Transact-SQL) для анализа XML.

-- You already had an example of @usedItems 
-- declared and populated in the question
declare @usedItems table(itemID int)
insert into @usedItems(itemID)
select 1 union
select 2

-- Build some XML, either directly or from a query
-- Here I demonstrate using a query
declare @itemsXML nvarchar(max);
select @itemsXML = 
    '<Items>' 
    + (select itemID from @usedItems as Item for xml auto) 
    + '</Items>'

print @itemsXML

-- Pass @itemsXML to the stored procedure as nvarchar(max)

-- Inside the procedure, use OPENXML to turn the XML 
-- back into a rows you can work with easily

DECLARE @idoc int
EXEC sp_xml_preparedocument @idoc OUTPUT, @itemsXML

SELECT  *
FROM    OPENXML (@idoc, '/Items/Item',1)
        WITH (itemID  int)

EXEC sp_xml_removedocument @idoc

Результаты

<Items><Item itemID="1"/><Item itemID="2"/></Items>
itemID
-----------
1
2
...