Inserting AutoIncrementID into DB - c#

Hi i'm having trouble with inserting incremented userid inside my db below is my table,stored proc,and my code.
CREATE TABLE [dbo].[Assignment2]
(
userID int PRIMARY KEY IDENTITY(1,1),
Name varchar(255) NOT NULL,
Age int NOT NULL,
Hobbies varchar(255)
)
and a stored procedure
ALTER PROCEDURE [db].[p_Assignment2_ins]
#userID int,
#Name nvarchar(100),
#Age int,
#Hobbies nvarchar(100)
AS
INSERT INTO [DB].[db].[Assignment2]
([Name]
,[Age]
,[Hobbies])
VALUES
(#Name
,#Age
,#Hobbies)
If ##Error <> 0
Return -1
Select #userID = ##Identity // this one just get the latest id that we inserted right?
Return 0
I have some question :
I want to know how do we insert the UserID from the code behind because If the table is empty at first shouldn't we insert a data first into the table
How do we generate an AutoIncrementID from codebehind and insert it
SqlConnection conn = new SqlConnection(ts.ConnMethod());
SqlCommand cmd = new SqlCommand("p_Assignment2_ins", conn);
cmd.CommandType = CommandType.StoredProcedure;
//I'm missing how we should add the IncrementedID
cmd.Parameters.AddWithValue("#Name", TextBox1.Text);
cmd.Parameters.AddWithValue("#Age", TextBox2.Text);
cmd.Parameters.AddWithValue("#Hobbies", TextBox3.Text);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
Any help is really appreciated thanks

Select #userID = ##Identity // this one just get the latest id that we inserted right?
No, you should use SCOPE_IDENTITY(). ##Identity returns the last id, yes, but not the last id from your insert. If you have a trigger, for example, that also produces an insert on a another table as a result of your insert, you will get the id inserted on the other table by that trigger.
Here's a nice article explaining the differences.
As far as inserting autoincrement values on your table; you can't do this unless you disable the constraint first but in essence, this shouldn't be necessary unless you are doing some sort of data import. In your scenario, you should be able to just insert values on the other columns except the identity field with autoincrement. The database will take care of inserting the appropriate value for you.

If you have AUTOINCREMENT field, you SHOULD NOT insert and generate values at all. DB is doing all by itself. So, remove the code that inserts ID-s

Related

Inserting across several tables using joins and junction table

I do apologize, I know this question pops up a lot, but I'm afraid I just don't understand the answers I've read on the subject and was hoping someone could clear things up for me.
I have three tables:
Recipes (ID int primary identity, RecipeName varchar(20), Directions varchar(max), RecIngID int)
Ingredients (ID int primary identity, IngredientName varchar(30), Quantity int)
and a junction table, Recipe_Ingredients (RecipeID int foreign key references Recipe(ID), IngredientID int foreign key references Ingredient(ID)
Now, that being said, I need to create stored procedures for everything (because I'm creating an ntier program using asp.net MVC 4 and C#, blah blah blah....
But I have no clue how to write a stored procedure for inserting a new recipe into that table, and taking into account the relationship between the junction table Recipe_Ingredients and the Ingredient table.
Can someone please, PLEASE help me here? All the explanations I've read haven't really made sense. If there's something I'm doing wrong, please tell me.
for each ingredient call this stored procedure
create procedure insertIngredients
(
#name varchar,
#quantity int
)
as
insert into Ingredients (IngredientName, Quantity)
values (#name, #quantity)
select SCOPE_IDENTITY()
which inserts ingredient and returns it's newly inserted ID.
Store that ids into some variable (ie, List or comma delimited string).
After that, insert recipe calling procedure:
create procedure insertRecipe
(
#name varchar,
#directions varchar(max),
#RecIngID int
)
as
insert into Recipes (RecipeName, Directions, RecIngID)
values (#name, #directions, #RecIngID)
select SCOPE_IDENTITY()
also save ID which that procedure returns after insert.
And, as last step insert data into junction table using recipe ID and all those Ingredient ID's you previously inserted.
create procedure insertRecipeIngredients
(
#recipeID int,
#ingredientID int
)
as
insert into Recipe_Ingredients (RecipeID, IngredientID)
values (#recipeID, #ingredientID)
select SCOPE_IDENTITY()
in your c# code call procedures like this:
public int InsertIngredient(string name, int quantity)
{
SqlConnection conn = new SqlConnection("[your connection string goes here]");
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "insertIngredients";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#name", name);
cmd.Parameters.AddWithValue("#quantity", quantity);
conn.Open();
int newlyInsertedId = (int) cmd.ExecuteScalar();
if (conn.State == System.Data.ConnectionState.Open)
conn.Close();
return newlyInsertedId;
}

Inserting Foreign key using primary key in asp.net

I am making a form in asp using C# and my task is to make a course and packages detail and insert the , i have make three tables one is Course which contain Id(pk) and Course-name, packages table contain Id(pk) and pkg-name and other table is Pkg-detail which contain Pkg-id(pk) and it is foreign key for Id in packages table and other attribute is course-id it is foreign key for course(ID) and my task is when i select pkg-name from drop down and course from check box from asp form that particular Id for pkg-name and Id for Course-name will insert in third table pkg-detail as i am new i have searched lot but cannot find related answer.
SqlCommand cmm = new SqlCommand("Pkc", con);
cmm.CommandType = CommandType.StoredProcedure;
cmm.Parameters.AddWithValue("#pname", drop1.SelectedValue);
cmm.Parameters.AddWithValue("#course", check1.SelectedValue);
con.Open();
cmm.ExecuteNonQuery();
con.Close();
CREATE PROCEDURE [dbo].[Pkc]
#course nvarchar(50),
#pname nvarchar(50)
AS
begin
insert into Pkg(CourseId)values((select Id from Courses where CourseName=#course));
insert into Pkg(PkgId) values ((select Id from PKgCode where PkgName=#pname))
end
You didn't mentioned your problem, but from your text it seems that you want to pass courceID and PackageID into your StoredProc, your code has a problem, since dropdown.SelectedValue is string by AddWithValue you will add two string parameter while I think they should be integer. So cast them as int or use other method that accepts type of parameter.
Edit
Base on comments it seems that your procedure should be like this:
CREATE PROCEDURE [dbo].[Pkc] #course nvarchar(50), #pname nvarchar(50)
AS
begin
declare #courceID int
declare #pkgID int
select #courceID = Id from Courses where CourseName=#course
select #pkgID = Id from PKgCode where PkgName=#pname
insert into Pkg-Detail(CourseId,PkgId) values(#courceID, #pkgID)
end

Uupdate values in two tables via stored procedure

I have two tables and I need to update values in them via a stored procedure. Tried too much to update but some times it update the first table only, others the second or even fail due to cannot allow duplicates. Also when it updates the WHOLE data in the table becomes the same as the new updated ones. I've now reached to this error after all these lines of codes
Cannot insert the value NULL into column 'Emp_ID',table 'DatePics'; column does not allow nulls. UPDATE fails.The statement has been terminated
Here is the SQL code :
ALTER procedure [dbo].[UpdateEmp]
#EmpName nvarchar(100),
#Nationality nvarchar(30),
#Passport nvarchar(20),
#ContractDate date,
#HealthDate date
AS
BEGIN
set nocount on;
DECLARE #IDs table (ID int )
UPDATE Employee SET
EmpName=#EmpName, Nationality=#Nationality, Visa=#Visa, Passport=#Passport,
ReceivedDate=#ReceivedDate,IDIssue=#IDIssue, IDExpiry=#IDExpiry, Sponsor=#Sponsor
output inserted.ID into #IDs (ID)
WHERE ID = #ID
UPDATE DatePics SET
FingerDate=#FingerDate, ContractDate=#ContractDate, HealthDate=#HealthDate
where Emp_ID in (select ID from #IDs);
END
After writing the stored procedure code, I wrote the C# code like this:
private void updatebtn_Click(object sender, EventArgs e)
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = db.con;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "UpdateEmp";
cmd.Parameters.AddWithValue("#EmpName", NameSeartxt.Text);
cmd.Parameters.AddWithValue("#Nationality", NatSeartxt.Text);
cmd.Parameters.AddWithValue("#Passport", PassSeartxt.Text);
cmd.Parameters.AddWithValue("#ContractDate", ContractSeartxt.Text);
cmd.Parameters.AddWithValue("#HealthDate", HealthSeartxt.Text);
db.con.Open();
int up = cmd.ExecuteNonQuery();
if (up > 0)
{
MessageBox.Show("Update done ", "DONE !");
SearNametxt.Text = "";
}
else
{
MessageBox.Show("Failed to update", "FAIL !");
SearNametxt.Text = "";
}
db.con.Close();
}
Any clue?
I can see three problems with your query. 1 You declare ID, but don't assign it before using it, so it will always be NULL for the first query, so this will never update any rows:
DECLARE #ID int
UPDATE FrstTable SET
EmpName=#EmpName, Nationality=#Nationality, Passport=#Passport
WHERE ID = #ID
Secondly, you are using SCOPE_IDENTITY to attempt to get the ID of the record that has been updated. You can't do that, SCOPE_IDENTITY will return the last inserted ID, it is not affected by updates. You will need to use OUTPUT to get the Updated ID:
DECLARE #IDs TABLE (ID INT);
UPDATE FirstTable
OUTPUT inserted.ID INTO #Ids (ID)
SET EmpName = #EmpName,
Nationality = #Nationality,
Passport = #Passport;
Thirdly, your second update statement has no where clause, so will update the entire table:
UPDATE ScndTable
SET Emp_ID=#ID, ContractDate=#ContractDate, HealthDate=#HealthDate
WHERE EmpID IN (SELECT ID FROM #Ids);
Your stored procedure looks weird to me. I believe there should be a WHERE cluase for the second UPDATE otherwise it will always update the whole ScndTable table. set #ID = SCOPE_IDENTITY(); seems to be reduntant here. Are you trying to perform insert into ScndTable if there's no corresponding Emp_ID there? Finnaly explicitly create a transaction to update either both tables or none.
Hope it helps!
Please assign the value of #ID variable, before executing the first update statement.
I think you are trying to update some row, so you can pass the 'id' value from the CSHARP code. When you use the SCOPE_IDENTITY, you will get the last inserted value. Try to pass the ID value from the front end.

C#/SQL get autoincremented field value

I have a table with autoincremented primary key. In my code I am trying to receive the new autoincremented value when I execute each 'insert' query. Is there a way to do it programatically?
Thanks.
UPD:
Assume I have a table:
TABLE User ( userID INT NOT NULL AUTO_INCREMENT, name VARCHAR( 25 ) NOT NULL , email VARCHAR( 50 ) NOT NULL , UNIQUE ( userID ) );
And I when I insert new values (name and email) to this table I want automatically receive newly generated userID. Ideally I am looking for any ways to do that with a single transaction and without stored procedures.
Have your sql/stored proc return scope_identity() or if you are using Linq2SQL or EF the entity used for insertion gets the new id.
In the stored proc it is:
ALTER proc [dbo].[SaveBuild](
#ID int = 0 output,
#Name varchar(150)=null,
#StageID int,
#Status char(1)=null
)
as
SET NOCOUNT ON
Insert into Builds
(name, StageID, status)
values (#Name, #StageID, #Status)
select #ID = scope_identity()
RETURN #ID
In the C# code you have:
public int SaveBuild(ref int id, ref string Name)
{
SqlCommand cmd = GetNewCmd("dbo.SaveBuild");
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = id;
cmd.Parameters["#ID"].Direction = ParameterDirection.InputOutput;
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = Name;
cmd.Parameters.Add("#StageID", SqlDbType.Int).Value = 0;
ExecuteNonQuery(cmd);
id = (int)cmd.Parameters["#ID"].Value;
return id;
}
Dependent upon your situation, you might be better off using table-valued parameters to pass your inserts to a stored procedure, then use OUTPUT INSERTED to return a table-valued parameter from your stored procedure.
It will drastically reduce the number of hits required if you're processing multiple items.
Are you limited to building SQL on the client and sending it to the server? Cause if you can use a stored procedure, this is easy to do. In the stored proc, do the insert and then, either
Select Scope_Identity() as the last statement in the stored proc., or
Use a output parameter to the stored proc, (say named #NewPKValue) and make the last statement:
Set #NewPKValue = Scope_Identity()
Otherwise, you need to send a batch of commands to the server that include two statements, the insert, and Select Scope_Identity() and execute the batch as though it was a select statement
You could use the SQL statement SELECT scope_identity().

Getting autonumber primary key from MS SQL Server

I am currently working in C#, and I need to insert a new record into one table, get the new primary key value, and then use that as a foreign key reference in inserting several more records. The Database is MS SQL Server 2003. All help is appreciated!
The way to get the identity of the inserted row is with the SCOPE_IDENTITY() function. If you're using stored procedures then this would look something like the following to return the row identity as an output parameter.
CREATE PROCEDURE dbo.MyProcedure
(
#RowId INT = NULL OUTPUT
)
AS
INSERT INTO MyTable
(
Column1
,Column2
,...
)
VALUES
(
#Param1
,#Param2
,...
);
SET #RowId = SCOPE_IDENTITY();
You can then use this value for any subsequent inserts (alternatively, if you can pass the data all into the stored procedure, then you can use it in the remainder of the procedure body).
If you're passing the SQL in dynamically then you use much the same technique, but with a single string with statement delimiters (also ; in SQL), e.g.:
var sql = "INSERT INTO MyTable (Column1, Column2, ...) VALUES (#P1, #P2, ...);" +
"SELECT SCOPE_IDENTITY();";
Then if you execute this using ExecuteScalar you'll be able to get the identity back as the scalar result and cast it to the right type. Alternatively you could build up the whole batch in one go, e.g.
var sql = "DECLARE #RowId INT;" +
"INSERT INTO MyTable (Column1, Column2, ...) VALUES (#P1, #P2, ...);" +
"SET #RowId = SCOPE_IDENTITY();" +
"INSERT INTO MyOtherTable (Column1, ...) VALUES (#P3, #P4, ...);";
This may not be exactly the right syntax, and you may need to use SET NOCOUNT ON; at the start (my mind is rusty as I rarely use dynamic SQL) but it should get you on the right track.
The best way of doing this is the use SCOPE_IDENTITY() function in TSQL. This should be executed as part of the insert i.e.
SqlCommand cmd = new SqlCommand(#"
INSERT INTO T (Name) VALUES(#Name)
SELECT SCOPE_IDENTITY() As TheId", conn);
cmd.AddParameter("#Name", SqlDbType.VarChar, 50).Value = "Test";
int tId = (int)cmd.ExecuteScalar();
Alternatively you can assign SCOPE_IDENTITY() to a variable to be used in successive statements. e.g.
DECLARE #T1 int
INSERT INTO T (Name) VALUES('Test')
SELECT #T1 = SCOPE_IDENTITY()
INSERT INTO T2 (Name, TId) VALUES('Test', #T1)
If you are just using SQL then check Duncan's answer. If however you are using LINQ then you can create the entity, save it to the DB and the ID parameter will be populated automatically.
Given a user entity and a user table it might look like this:
using(var db = new DataContext()) {
var user = new User { Name = "Jhon" };
db.Users.InsertOnSubmit(user);
db.SubmitChanges();
/* At this point the user.ID field will have the primary key from the database */
}

Categories

Resources