通过存储过程在Order表中插入一行,在OrderDetails表中插入多行

时间:2014-03-12 01:26:03

标签: sql sql-server database tsql

我有五个名为guestordersorder_detailsfoodemployees的表格。它们的特点如下:

create table guest 
(
 guest_id int primary key identity(1,1),
 guest_fname nvarchar(50),
 national_id int,
 mobile nvarchar(50),
 nationality_id int
constraint c15
          foreign key(nationality_id) references nationality(nationality_id)
)
create table employees
 (
  emp_id int primary key ,
  emp_fname nvarchar(50),
  constraint c1
  --foreign key(mgr_id) references employees(emp_id),
  foreign key(super_id) references employees(emp_id),
  )
  go
  create table food 
  (
   food_id  int primary key identity(1,1),
   food_name nvarchar(50),
   food_price money,
   food_desc nvarchar(200),
   cat_id int
   constraint c5
   foreign key(cat_id) references food_categories(cat_id)
  )
  go
  create table orders
  (
   order_id int primary key identity(1,1),
   order_date datetime,
   total float,
   guest_id int,
   emp_id int,
   is_paid bit
   constraint c6
   foreign key(guest_id) references guest(guest_id),
   foreign key(emp_id) references employees(emp_id)
  )
  go
  create table order_details
  (
   order_id int,
   food_id int,
   price money,
   qty int
   constraint c7
   primary key(order_id,food_id),
   foreign key(order_id) references orders(order_id),
   foreign key(food_id) references food(food_id)
  )
  Go

ordersorder_details之间存在1对M的关系。

我想通过存储过程将一行插入orders,将多行插入order_details。请帮帮我!

请给我一个存储过程并解释它的算法,指出我正确的方向。

2 个答案:

答案 0 :(得分:0)

正如@ thepirat000指出的那样,您可以使用TVP作为订单详细信息/订单项,因为您使用的是SQL Server 2012.Pinal Dave有great article on TVPs您可能会觉得有帮助。将TVP与标量参数组合以获得订单属性。

例如:

-- NOTE: *Not* accounting for order_id in this case - i.e. a new order where
-- order_id is an identity value.
CREATE TYPE [dbo].[order_details_type] AS TABLE
(
    food_id int,
    price money,
    qty int
)
GO

CREATE PROCEDURE [dbo].[usp_insert_order]
(
   @order_id int output,
   @order_date datetime = NULL,
   @total float,
   @guest_id int,
   @emp_id int,
   @is_paid bit = 0,
   @details order_details_type readonly
)
AS
BEGIN
    SET NOCOUNT ON;

    -- TODO: Wrap the inserts into dbo.orders and dbo.order_details in a
    -- transaction as desired.

    -- TODO: Check that @order_id does not already exist in dbo.orders and
    -- dbo.order_details etc.

    -- FORNOW: Proceed optimistically. :}

    IF @order_date IS NULL
        SET @order_date = GETDATE();

    INSERT INTO dbo.orders (order_date, total, guest_id, emp_id, is_paid)
    VALUES (@order_date, @total, @guest_id, @emp_id, @is_paid);

    SET @order_id = SCOPE_IDENTITY();

    INSERT INTO dbo.order_details (order_id, food_id, price, qty)
    SELECT @order_id, food_id, price, qty
    FROM @details;
END
GO

执行这样的存储过程非常简单,因为您准备TVP参数就像表变量一样:

/*
 * Order up!
 */

/* data I added for a quick check
SELECT TOP 1 * FROM dbo.employees;
--emp_id    emp_fname
--1 Wendy

SELECT TOP 1 * FROM dbo.guest;
--guest_id  guest_fname national_id mobile
--1 Joe 1   619-555-1212

SELECT TOP 2 * FROM dbo.food;
--food_id   food_name   food_price  food_desc
--1 Onion Rings 5.00    Beer-battered onion rings.
--2 Kobe Burger 10.00   Kobe-beef burger.
*/

-- Prepare the order.
DECLARE @order_id int; -- to get on order insert
DECLARE @now datetime = getdate();
DECLARE @order_details order_details_type;

INSERT INTO @order_details
SELECT 1, 5, 1
UNION
SELECT 2, 10, 2;

-- Insert the order.
EXEC dbo.usp_insert_order
    @order_id = @order_id OUTPUT,
    @order_date=@now,
    @total=25,
    @guest_id=1,
    @emp_id=1,
    @is_paid=0,
    @details=@order_details;

/*
 * Check the order.
 */

SELECT * FROM dbo.orders WHERE order_id = @order_id;
--order_id  order_date  total   guest_id    emp_id  is_paid
--1 2014-03-13 21:44:45.400 25  1   1   0

SELECT * FROM dbo.order_details WHERE order_id = @order_id;
--order_id  food_id price   qty
--1 1   5.00    1
--1 2   10.00   2

TVP之前的另一个选项也可能会让您感兴趣 - using an XML parameter订单明细/订单项和订单属性的标量参数。相关资源和例子比比皆是。

XML-param方法的一种变体,即为订单传递XML详细信息/订单项;但我觉得这个人个人有点过分了。

答案 1 :(得分:-1)

你需要2个存储过程,1个用于订单,1个用于Order_details,在最后一个为食品表数量添加更新语句。你不想为所有

制作1个sproc