开发者

SQL Server: Stored Proc input table variable workaround

开发者 https://www.devze.com 2023-02-05 14:29 出处:网络
I\'m trying to find a good work around to not being able to use a table variable as an input to a stored procedure.I want to insert a single record into a base table and multiple records into a pivot

I'm trying to find a good work around to not being able to use a table variable as an input to a stored procedure. I want to insert a single record into a base table and multiple records into a pivot table. My initial thought process led me to wanting a stored proc with separate inputs for the base table, and a single list input for the pivot table records, i.e.:

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

As already stated, the above code won't work because of the table variable input, @items (I believe primarily due to variable scope issues). So, are there any good workarounds to this?

Original Question

I have three tables:

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)
)

With some initial item data:

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'

And I have some code for creating a new task:

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

Now, I want a way of simplifying/streamlining the creation of new tasks. My first thought w开发者_开发问答as to use a stored proc, but table variables can't be used as inputs, so it won't work. I think I can do this with a view with an insert trigger, but I'm not sure... Is that my best (or only) option?


I have had great luck using XML to pass data to procedures. You can use OPENXML (Transact-SQL) to parse the 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

Results

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

精彩评论

暂无评论...
验证码 换一张
取 消