Adding one to many records in stored procedure









up vote
2
down vote

favorite












I need help from someone who knows SQL, because that is a problem beyond my SQL skills. That are my tables :



CREATE TABLE [dbo].[Orders]
(
id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
customerName VARCHAR(30) NOT NULL,
customerAddress VARCHAR(30) NOT NULL,
submitDate DATE NOT NULL,
realizationDate DATE,
deliveryTypeId INT NOT NULL

FOREIGN KEY(deliveryTypeId) REFERENCES deliveryTypes(id)
);

CREATE TABLE [dbo].[OrderItems]
(
id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
orderId INT NOT NULL,
productId INT NOT NULL,
productQuantity INT,

FOREIGN KEY(orderId) REFERENCES Orders(id),
FOREIGN KEY(productId) REFERENCES Products(id)
);


I need to create a stored procedure that inserts to two tables in the database one to many related records (in fact that's really part of many-to-many bindings, but I need to add only to these two tables). In my application (.NET) I need to pass one record "Orders" and one or more records "OrderItems".



My problems are:



  • If I insert "Order" I will not know what value to set in OrderItems -> orderId. I found the SCOPE_IDENTITY function, but I do not really know how to use it in my case.

  • How do I insert OrderItems records in the table if I do not know how many of them will be? I only know that there can be one or more of them.

  • I do not know how to call the procedure receiving many OrderItems from the application level and what arguments should I declare in the stored procedure

I really appreciate all the help, because I face a few hours with this problem and I really do not know how to do it.



EDIT : This is the code that I've come up with so far:



CREATE PROCEDURE spAddOrder
(@customerName VARCHAR(30),
@customerAddress VARCHAR(30),
@submitDate DATE,
@deliveryTypeId INT
-- I don't know how to pass many OrderItems rows as argument
)
AS
BEGIN
INSERT INTO Orders(customerName, customerAddress, submitDate, deliveryTypeId)
VALUES (@customerName, @customerAddress, @submitDate, @deliveryTypeId)

SELECT SCOPE_IDENTITY() AS orderId

-- I don't know how to do it for unknown number of rows
INSERT INTO OrderItems(orderId, productId, productQuantity)
VALUES (@orderId, @productId, @productQuantity)
END;
GO









share|improve this question























  • I'd recommend you to ask in dba.stackexchange.com as well
    – Barr J
    Nov 11 at 6:33










  • @BarrJ Thanks for the suggestion, I will do it
    – marryN
    Nov 11 at 6:43










  • It would be awesome if you could share a Minimal, Complete, and Verifiable example of your progress so far.
    – mjwills
    Nov 11 at 6:45










  • @mjwills I have just edit my question, thanks for your answer below.
    – marryN
    Nov 11 at 7:18














up vote
2
down vote

favorite












I need help from someone who knows SQL, because that is a problem beyond my SQL skills. That are my tables :



CREATE TABLE [dbo].[Orders]
(
id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
customerName VARCHAR(30) NOT NULL,
customerAddress VARCHAR(30) NOT NULL,
submitDate DATE NOT NULL,
realizationDate DATE,
deliveryTypeId INT NOT NULL

FOREIGN KEY(deliveryTypeId) REFERENCES deliveryTypes(id)
);

CREATE TABLE [dbo].[OrderItems]
(
id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
orderId INT NOT NULL,
productId INT NOT NULL,
productQuantity INT,

FOREIGN KEY(orderId) REFERENCES Orders(id),
FOREIGN KEY(productId) REFERENCES Products(id)
);


I need to create a stored procedure that inserts to two tables in the database one to many related records (in fact that's really part of many-to-many bindings, but I need to add only to these two tables). In my application (.NET) I need to pass one record "Orders" and one or more records "OrderItems".



My problems are:



  • If I insert "Order" I will not know what value to set in OrderItems -> orderId. I found the SCOPE_IDENTITY function, but I do not really know how to use it in my case.

  • How do I insert OrderItems records in the table if I do not know how many of them will be? I only know that there can be one or more of them.

  • I do not know how to call the procedure receiving many OrderItems from the application level and what arguments should I declare in the stored procedure

I really appreciate all the help, because I face a few hours with this problem and I really do not know how to do it.



EDIT : This is the code that I've come up with so far:



CREATE PROCEDURE spAddOrder
(@customerName VARCHAR(30),
@customerAddress VARCHAR(30),
@submitDate DATE,
@deliveryTypeId INT
-- I don't know how to pass many OrderItems rows as argument
)
AS
BEGIN
INSERT INTO Orders(customerName, customerAddress, submitDate, deliveryTypeId)
VALUES (@customerName, @customerAddress, @submitDate, @deliveryTypeId)

SELECT SCOPE_IDENTITY() AS orderId

-- I don't know how to do it for unknown number of rows
INSERT INTO OrderItems(orderId, productId, productQuantity)
VALUES (@orderId, @productId, @productQuantity)
END;
GO









share|improve this question























  • I'd recommend you to ask in dba.stackexchange.com as well
    – Barr J
    Nov 11 at 6:33










  • @BarrJ Thanks for the suggestion, I will do it
    – marryN
    Nov 11 at 6:43










  • It would be awesome if you could share a Minimal, Complete, and Verifiable example of your progress so far.
    – mjwills
    Nov 11 at 6:45










  • @mjwills I have just edit my question, thanks for your answer below.
    – marryN
    Nov 11 at 7:18












up vote
2
down vote

favorite









up vote
2
down vote

favorite











I need help from someone who knows SQL, because that is a problem beyond my SQL skills. That are my tables :



CREATE TABLE [dbo].[Orders]
(
id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
customerName VARCHAR(30) NOT NULL,
customerAddress VARCHAR(30) NOT NULL,
submitDate DATE NOT NULL,
realizationDate DATE,
deliveryTypeId INT NOT NULL

FOREIGN KEY(deliveryTypeId) REFERENCES deliveryTypes(id)
);

CREATE TABLE [dbo].[OrderItems]
(
id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
orderId INT NOT NULL,
productId INT NOT NULL,
productQuantity INT,

FOREIGN KEY(orderId) REFERENCES Orders(id),
FOREIGN KEY(productId) REFERENCES Products(id)
);


I need to create a stored procedure that inserts to two tables in the database one to many related records (in fact that's really part of many-to-many bindings, but I need to add only to these two tables). In my application (.NET) I need to pass one record "Orders" and one or more records "OrderItems".



My problems are:



  • If I insert "Order" I will not know what value to set in OrderItems -> orderId. I found the SCOPE_IDENTITY function, but I do not really know how to use it in my case.

  • How do I insert OrderItems records in the table if I do not know how many of them will be? I only know that there can be one or more of them.

  • I do not know how to call the procedure receiving many OrderItems from the application level and what arguments should I declare in the stored procedure

I really appreciate all the help, because I face a few hours with this problem and I really do not know how to do it.



EDIT : This is the code that I've come up with so far:



CREATE PROCEDURE spAddOrder
(@customerName VARCHAR(30),
@customerAddress VARCHAR(30),
@submitDate DATE,
@deliveryTypeId INT
-- I don't know how to pass many OrderItems rows as argument
)
AS
BEGIN
INSERT INTO Orders(customerName, customerAddress, submitDate, deliveryTypeId)
VALUES (@customerName, @customerAddress, @submitDate, @deliveryTypeId)

SELECT SCOPE_IDENTITY() AS orderId

-- I don't know how to do it for unknown number of rows
INSERT INTO OrderItems(orderId, productId, productQuantity)
VALUES (@orderId, @productId, @productQuantity)
END;
GO









share|improve this question















I need help from someone who knows SQL, because that is a problem beyond my SQL skills. That are my tables :



CREATE TABLE [dbo].[Orders]
(
id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
customerName VARCHAR(30) NOT NULL,
customerAddress VARCHAR(30) NOT NULL,
submitDate DATE NOT NULL,
realizationDate DATE,
deliveryTypeId INT NOT NULL

FOREIGN KEY(deliveryTypeId) REFERENCES deliveryTypes(id)
);

CREATE TABLE [dbo].[OrderItems]
(
id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
orderId INT NOT NULL,
productId INT NOT NULL,
productQuantity INT,

FOREIGN KEY(orderId) REFERENCES Orders(id),
FOREIGN KEY(productId) REFERENCES Products(id)
);


I need to create a stored procedure that inserts to two tables in the database one to many related records (in fact that's really part of many-to-many bindings, but I need to add only to these two tables). In my application (.NET) I need to pass one record "Orders" and one or more records "OrderItems".



My problems are:



  • If I insert "Order" I will not know what value to set in OrderItems -> orderId. I found the SCOPE_IDENTITY function, but I do not really know how to use it in my case.

  • How do I insert OrderItems records in the table if I do not know how many of them will be? I only know that there can be one or more of them.

  • I do not know how to call the procedure receiving many OrderItems from the application level and what arguments should I declare in the stored procedure

I really appreciate all the help, because I face a few hours with this problem and I really do not know how to do it.



EDIT : This is the code that I've come up with so far:



CREATE PROCEDURE spAddOrder
(@customerName VARCHAR(30),
@customerAddress VARCHAR(30),
@submitDate DATE,
@deliveryTypeId INT
-- I don't know how to pass many OrderItems rows as argument
)
AS
BEGIN
INSERT INTO Orders(customerName, customerAddress, submitDate, deliveryTypeId)
VALUES (@customerName, @customerAddress, @submitDate, @deliveryTypeId)

SELECT SCOPE_IDENTITY() AS orderId

-- I don't know how to do it for unknown number of rows
INSERT INTO OrderItems(orderId, productId, productQuantity)
VALUES (@orderId, @productId, @productQuantity)
END;
GO






c# sql stored-procedures one-to-many sql-server-2017






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 11 at 7:43









marc_s

567k12710961246




567k12710961246










asked Nov 11 at 6:31









marryN

163




163











  • I'd recommend you to ask in dba.stackexchange.com as well
    – Barr J
    Nov 11 at 6:33










  • @BarrJ Thanks for the suggestion, I will do it
    – marryN
    Nov 11 at 6:43










  • It would be awesome if you could share a Minimal, Complete, and Verifiable example of your progress so far.
    – mjwills
    Nov 11 at 6:45










  • @mjwills I have just edit my question, thanks for your answer below.
    – marryN
    Nov 11 at 7:18
















  • I'd recommend you to ask in dba.stackexchange.com as well
    – Barr J
    Nov 11 at 6:33










  • @BarrJ Thanks for the suggestion, I will do it
    – marryN
    Nov 11 at 6:43










  • It would be awesome if you could share a Minimal, Complete, and Verifiable example of your progress so far.
    – mjwills
    Nov 11 at 6:45










  • @mjwills I have just edit my question, thanks for your answer below.
    – marryN
    Nov 11 at 7:18















I'd recommend you to ask in dba.stackexchange.com as well
– Barr J
Nov 11 at 6:33




I'd recommend you to ask in dba.stackexchange.com as well
– Barr J
Nov 11 at 6:33












@BarrJ Thanks for the suggestion, I will do it
– marryN
Nov 11 at 6:43




@BarrJ Thanks for the suggestion, I will do it
– marryN
Nov 11 at 6:43












It would be awesome if you could share a Minimal, Complete, and Verifiable example of your progress so far.
– mjwills
Nov 11 at 6:45




It would be awesome if you could share a Minimal, Complete, and Verifiable example of your progress so far.
– mjwills
Nov 11 at 6:45












@mjwills I have just edit my question, thanks for your answer below.
– marryN
Nov 11 at 7:18




@mjwills I have just edit my question, thanks for your answer below.
– marryN
Nov 11 at 7:18












1 Answer
1






active

oldest

votes

















up vote
5
down vote













While this question might be considered as too broad and therefor off topic, it is well written and describe a problem a lot of inexperienced developers are facing - so I think it deserves an answer.

So let's break it down to its ingredients:



  1. Q: How to get the value of the identity column back after an insert?
    A: SQL Server provides several ways to do that, the simplest would probably be scope_identity, but the best would be using the output clause.


  2. Q: How to send multiple rows to a stored procedure?
    A: Use a table valued parameter.


Now let's see how exactly are we going to do this.



The first thing we need to do is create a user defined table type to be used for the table valued parameter - so:



CREATE TYPE [dbo].[Udt_OrderItems] AS TABLE
(
productId int NOT NULL,
productQuantity int,
);
GO


Then, we can create a stored procedure using this type as a table valued parameter.
We will also send the order details as scalar parameters to the stored procedure:



CREATE PROCEDURE stp_InsertOrderWithItems
(
@customerName varchar(30),
@customerAddress varchar(30),
@submitDate date,
@realizationDate date,
@deliveryTypeId int,
@orderItems dbo.Udt_OrderItems readonly -- Table valued parameters must be readonly
)
AS

DECLARE @Ids AS TABLE (orderId int NOT NULL) -- for the output clause

INSERT INTO dbo.Orders (customerName, customerAddress, submitDate, realizationDate, deliveryTypeId)
OUTPUT inserted.Id INTO @Ids
VALUES(@customerName, @customerAddress, @submitDate, @realizationDate, @deliveryTypeId)

INSERT INTO dbo.OrderItems (orderId, productId, productQuantity)
SELECT orderId, productId, productQuantity
FROM @orderItems
CROSS JOIN @Ids -- We only have one value in @Ids so cross join is safe
GO


As for the c# part, It depends how are you connecting to the database - I'll show an example of the basic ADO.Net version:



using(var con = new SqlConnection(connectionString))

using(var cmd = new SqlCommand(con, "stp_InsertOrderWithItems"))

var dt = new DataTable()
dt.Columns.Add("productId", typeof(int));
dt.Columns.Add("productQuantity", typeof(int));

// populate data table here

cmd.Parameters.Add("@customerName", SqlDbType.VarChar, 30).Value = customerName;
// all the other scalar parameters here...
cmd.Parameters.Add(@orderItems, SqlDbType.Structured).Value = dt;

con.Open();
cmd.ExecuteNonQuery();







share|improve this answer






















  • This is a great and helpfull explanation, but could you tell me what the purpose of orderIdint is? (stored procedure, 12 line)
    – marryN
    Nov 12 at 9:18






  • 1




    It's a typo - should be orderId int (that's a non-nullable int column on the @Ids table. Answer fixed.
    – Zohar Peled
    Nov 12 at 9:24










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53246406%2fadding-one-to-many-records-in-stored-procedure%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
5
down vote













While this question might be considered as too broad and therefor off topic, it is well written and describe a problem a lot of inexperienced developers are facing - so I think it deserves an answer.

So let's break it down to its ingredients:



  1. Q: How to get the value of the identity column back after an insert?
    A: SQL Server provides several ways to do that, the simplest would probably be scope_identity, but the best would be using the output clause.


  2. Q: How to send multiple rows to a stored procedure?
    A: Use a table valued parameter.


Now let's see how exactly are we going to do this.



The first thing we need to do is create a user defined table type to be used for the table valued parameter - so:



CREATE TYPE [dbo].[Udt_OrderItems] AS TABLE
(
productId int NOT NULL,
productQuantity int,
);
GO


Then, we can create a stored procedure using this type as a table valued parameter.
We will also send the order details as scalar parameters to the stored procedure:



CREATE PROCEDURE stp_InsertOrderWithItems
(
@customerName varchar(30),
@customerAddress varchar(30),
@submitDate date,
@realizationDate date,
@deliveryTypeId int,
@orderItems dbo.Udt_OrderItems readonly -- Table valued parameters must be readonly
)
AS

DECLARE @Ids AS TABLE (orderId int NOT NULL) -- for the output clause

INSERT INTO dbo.Orders (customerName, customerAddress, submitDate, realizationDate, deliveryTypeId)
OUTPUT inserted.Id INTO @Ids
VALUES(@customerName, @customerAddress, @submitDate, @realizationDate, @deliveryTypeId)

INSERT INTO dbo.OrderItems (orderId, productId, productQuantity)
SELECT orderId, productId, productQuantity
FROM @orderItems
CROSS JOIN @Ids -- We only have one value in @Ids so cross join is safe
GO


As for the c# part, It depends how are you connecting to the database - I'll show an example of the basic ADO.Net version:



using(var con = new SqlConnection(connectionString))

using(var cmd = new SqlCommand(con, "stp_InsertOrderWithItems"))

var dt = new DataTable()
dt.Columns.Add("productId", typeof(int));
dt.Columns.Add("productQuantity", typeof(int));

// populate data table here

cmd.Parameters.Add("@customerName", SqlDbType.VarChar, 30).Value = customerName;
// all the other scalar parameters here...
cmd.Parameters.Add(@orderItems, SqlDbType.Structured).Value = dt;

con.Open();
cmd.ExecuteNonQuery();







share|improve this answer






















  • This is a great and helpfull explanation, but could you tell me what the purpose of orderIdint is? (stored procedure, 12 line)
    – marryN
    Nov 12 at 9:18






  • 1




    It's a typo - should be orderId int (that's a non-nullable int column on the @Ids table. Answer fixed.
    – Zohar Peled
    Nov 12 at 9:24














up vote
5
down vote













While this question might be considered as too broad and therefor off topic, it is well written and describe a problem a lot of inexperienced developers are facing - so I think it deserves an answer.

So let's break it down to its ingredients:



  1. Q: How to get the value of the identity column back after an insert?
    A: SQL Server provides several ways to do that, the simplest would probably be scope_identity, but the best would be using the output clause.


  2. Q: How to send multiple rows to a stored procedure?
    A: Use a table valued parameter.


Now let's see how exactly are we going to do this.



The first thing we need to do is create a user defined table type to be used for the table valued parameter - so:



CREATE TYPE [dbo].[Udt_OrderItems] AS TABLE
(
productId int NOT NULL,
productQuantity int,
);
GO


Then, we can create a stored procedure using this type as a table valued parameter.
We will also send the order details as scalar parameters to the stored procedure:



CREATE PROCEDURE stp_InsertOrderWithItems
(
@customerName varchar(30),
@customerAddress varchar(30),
@submitDate date,
@realizationDate date,
@deliveryTypeId int,
@orderItems dbo.Udt_OrderItems readonly -- Table valued parameters must be readonly
)
AS

DECLARE @Ids AS TABLE (orderId int NOT NULL) -- for the output clause

INSERT INTO dbo.Orders (customerName, customerAddress, submitDate, realizationDate, deliveryTypeId)
OUTPUT inserted.Id INTO @Ids
VALUES(@customerName, @customerAddress, @submitDate, @realizationDate, @deliveryTypeId)

INSERT INTO dbo.OrderItems (orderId, productId, productQuantity)
SELECT orderId, productId, productQuantity
FROM @orderItems
CROSS JOIN @Ids -- We only have one value in @Ids so cross join is safe
GO


As for the c# part, It depends how are you connecting to the database - I'll show an example of the basic ADO.Net version:



using(var con = new SqlConnection(connectionString))

using(var cmd = new SqlCommand(con, "stp_InsertOrderWithItems"))

var dt = new DataTable()
dt.Columns.Add("productId", typeof(int));
dt.Columns.Add("productQuantity", typeof(int));

// populate data table here

cmd.Parameters.Add("@customerName", SqlDbType.VarChar, 30).Value = customerName;
// all the other scalar parameters here...
cmd.Parameters.Add(@orderItems, SqlDbType.Structured).Value = dt;

con.Open();
cmd.ExecuteNonQuery();







share|improve this answer






















  • This is a great and helpfull explanation, but could you tell me what the purpose of orderIdint is? (stored procedure, 12 line)
    – marryN
    Nov 12 at 9:18






  • 1




    It's a typo - should be orderId int (that's a non-nullable int column on the @Ids table. Answer fixed.
    – Zohar Peled
    Nov 12 at 9:24












up vote
5
down vote










up vote
5
down vote









While this question might be considered as too broad and therefor off topic, it is well written and describe a problem a lot of inexperienced developers are facing - so I think it deserves an answer.

So let's break it down to its ingredients:



  1. Q: How to get the value of the identity column back after an insert?
    A: SQL Server provides several ways to do that, the simplest would probably be scope_identity, but the best would be using the output clause.


  2. Q: How to send multiple rows to a stored procedure?
    A: Use a table valued parameter.


Now let's see how exactly are we going to do this.



The first thing we need to do is create a user defined table type to be used for the table valued parameter - so:



CREATE TYPE [dbo].[Udt_OrderItems] AS TABLE
(
productId int NOT NULL,
productQuantity int,
);
GO


Then, we can create a stored procedure using this type as a table valued parameter.
We will also send the order details as scalar parameters to the stored procedure:



CREATE PROCEDURE stp_InsertOrderWithItems
(
@customerName varchar(30),
@customerAddress varchar(30),
@submitDate date,
@realizationDate date,
@deliveryTypeId int,
@orderItems dbo.Udt_OrderItems readonly -- Table valued parameters must be readonly
)
AS

DECLARE @Ids AS TABLE (orderId int NOT NULL) -- for the output clause

INSERT INTO dbo.Orders (customerName, customerAddress, submitDate, realizationDate, deliveryTypeId)
OUTPUT inserted.Id INTO @Ids
VALUES(@customerName, @customerAddress, @submitDate, @realizationDate, @deliveryTypeId)

INSERT INTO dbo.OrderItems (orderId, productId, productQuantity)
SELECT orderId, productId, productQuantity
FROM @orderItems
CROSS JOIN @Ids -- We only have one value in @Ids so cross join is safe
GO


As for the c# part, It depends how are you connecting to the database - I'll show an example of the basic ADO.Net version:



using(var con = new SqlConnection(connectionString))

using(var cmd = new SqlCommand(con, "stp_InsertOrderWithItems"))

var dt = new DataTable()
dt.Columns.Add("productId", typeof(int));
dt.Columns.Add("productQuantity", typeof(int));

// populate data table here

cmd.Parameters.Add("@customerName", SqlDbType.VarChar, 30).Value = customerName;
// all the other scalar parameters here...
cmd.Parameters.Add(@orderItems, SqlDbType.Structured).Value = dt;

con.Open();
cmd.ExecuteNonQuery();







share|improve this answer














While this question might be considered as too broad and therefor off topic, it is well written and describe a problem a lot of inexperienced developers are facing - so I think it deserves an answer.

So let's break it down to its ingredients:



  1. Q: How to get the value of the identity column back after an insert?
    A: SQL Server provides several ways to do that, the simplest would probably be scope_identity, but the best would be using the output clause.


  2. Q: How to send multiple rows to a stored procedure?
    A: Use a table valued parameter.


Now let's see how exactly are we going to do this.



The first thing we need to do is create a user defined table type to be used for the table valued parameter - so:



CREATE TYPE [dbo].[Udt_OrderItems] AS TABLE
(
productId int NOT NULL,
productQuantity int,
);
GO


Then, we can create a stored procedure using this type as a table valued parameter.
We will also send the order details as scalar parameters to the stored procedure:



CREATE PROCEDURE stp_InsertOrderWithItems
(
@customerName varchar(30),
@customerAddress varchar(30),
@submitDate date,
@realizationDate date,
@deliveryTypeId int,
@orderItems dbo.Udt_OrderItems readonly -- Table valued parameters must be readonly
)
AS

DECLARE @Ids AS TABLE (orderId int NOT NULL) -- for the output clause

INSERT INTO dbo.Orders (customerName, customerAddress, submitDate, realizationDate, deliveryTypeId)
OUTPUT inserted.Id INTO @Ids
VALUES(@customerName, @customerAddress, @submitDate, @realizationDate, @deliveryTypeId)

INSERT INTO dbo.OrderItems (orderId, productId, productQuantity)
SELECT orderId, productId, productQuantity
FROM @orderItems
CROSS JOIN @Ids -- We only have one value in @Ids so cross join is safe
GO


As for the c# part, It depends how are you connecting to the database - I'll show an example of the basic ADO.Net version:



using(var con = new SqlConnection(connectionString))

using(var cmd = new SqlCommand(con, "stp_InsertOrderWithItems"))

var dt = new DataTable()
dt.Columns.Add("productId", typeof(int));
dt.Columns.Add("productQuantity", typeof(int));

// populate data table here

cmd.Parameters.Add("@customerName", SqlDbType.VarChar, 30).Value = customerName;
// all the other scalar parameters here...
cmd.Parameters.Add(@orderItems, SqlDbType.Structured).Value = dt;

con.Open();
cmd.ExecuteNonQuery();








share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 12 at 9:23

























answered Nov 11 at 6:55









Zohar Peled

51.5k73172




51.5k73172











  • This is a great and helpfull explanation, but could you tell me what the purpose of orderIdint is? (stored procedure, 12 line)
    – marryN
    Nov 12 at 9:18






  • 1




    It's a typo - should be orderId int (that's a non-nullable int column on the @Ids table. Answer fixed.
    – Zohar Peled
    Nov 12 at 9:24
















  • This is a great and helpfull explanation, but could you tell me what the purpose of orderIdint is? (stored procedure, 12 line)
    – marryN
    Nov 12 at 9:18






  • 1




    It's a typo - should be orderId int (that's a non-nullable int column on the @Ids table. Answer fixed.
    – Zohar Peled
    Nov 12 at 9:24















This is a great and helpfull explanation, but could you tell me what the purpose of orderIdint is? (stored procedure, 12 line)
– marryN
Nov 12 at 9:18




This is a great and helpfull explanation, but could you tell me what the purpose of orderIdint is? (stored procedure, 12 line)
– marryN
Nov 12 at 9:18




1




1




It's a typo - should be orderId int (that's a non-nullable int column on the @Ids table. Answer fixed.
– Zohar Peled
Nov 12 at 9:24




It's a typo - should be orderId int (that's a non-nullable int column on the @Ids table. Answer fixed.
– Zohar Peled
Nov 12 at 9:24

















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53246406%2fadding-one-to-many-records-in-stored-procedure%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

27

Top Tejano songwriter Luis Silva dead of heart attack at 64

Category:Rhetoric