Insert data into 2 related tables at once? - sql

I am trying to insert into two tables at once using the primary key from the first table to insert into the second but I am not sure how to go about it.
My table structure is as follows:
Person
PersonId
FirstName
Surname
Employee
EmployeeId
HoursWorked
PersonId in the Person table is an auto incremented column. EmployeeId in the second table is a primary and foreign key that should be the same as PersonId.
I been trying with this query string which I found on Google but with not much luck:
string queryString = "BEGIN TRANSACTION DECLARE #DataID int; "
+"INSERT INTO Person(FirstName, Surname) VALUES(#firstName, #surname);"
+ "SELECT #DataID = scope_identity();"
+ "INSERT INTO Employee VALUES(#DataId, #hoursWorked);"
+ "COMMIT";

From C#, you can try something like this:
// define the INSERT query - insert a firstname,surname into "Person",
// and insert a row into the Emplyoee table with the new ID
// created by the first insert
string insertStmt = #"BEGIN TRANSACTION
INSERT INTO dbo.Person(FirstName, Surname) VALUES(#FirstName, #Surname);
DECLARE #NewPersonId INT = SCOPE_IDENTITY();
INSERT INTO dbo.Employee(EmployeeId, HoursWorked) VALUES(#NewPersonId, #HoursWorked);
COMMIT TRANSACTION;"
// define connection and command for inserting data
using (SqlConnection conn = new SqlConnection(-your-connection-string-here-))
using (SqlCommand cmdInsert = new SqlCommand(insertStmt, conn))
{
// Define parameters - adapt datatype and max length as required
cmdInsert.Parameters.Add("#FirstName", SqlDbType.VarChar, 100);
cmdInsert.Parameters.Add("#Surname", SqlDbType.VarChar, 100);
cmdInsert.Parameters.Add("#HoursWorked", SqlDbType.Int);
// set parameter values
cmdInsert.Parameters["#FirstName"].Value = "John";
cmdInsert.Parameters["#Surname"].Value = "Doe";
cmdInsert.Parameters["#HoursWorked"].Value = 35;
// Open connection, execute query, close connection
conn.Open();
int rowsInserted = cmdInsert.ExecuteNonQuery();
conn.Close();
}
Update: as mentioned by #charlieface, you can write this code more concisely IF you're only ever inserting a single row - like this:
// define connection and command for inserting data
using (SqlConnection conn = new SqlConnection(-your-connection-string-here-))
using (SqlCommand cmdInsert = new SqlCommand(insertStmt, conn))
{
// Define and set parameters
cmdInsert.Parameters.Add("#FirstName", SqlDbType.VarChar, 100).Value = "John";
cmdInsert.Parameters.Add("#Surname", SqlDbType.VarChar, 100).Value = "Doe";
cmdInsert.Parameters.Add("#HoursWorked", SqlDbType.Int).Value = 35;
// Open connection, execute query, close connection
conn.Open();
int rowsInserted = cmdInsert.ExecuteNonQuery();
conn.Close();
}

You need to specify the columns you are inserting into.
You should also use SET XACT_ABORT ON if you have an explicit transaction.
Note also the use of a multi-line string.
string queryString = #"
SET XACT_ABORT ON;
BEGIN TRANSACTION;
INSERT INTO Person (FirstName, Surname)
VALUES(#firstName, #surname);
DECLARE #DataID int = scope_identity();
INSERT INTO Employee (EmployeeId, HoursWorked)
VALUES(#DataId, #hoursWorked);
COMMIT;
";

Related

Number of query values and destination fields are not the same (Union)

Running into this SQL error - number of query values and destination fields are not the same (Union). Using an Access database. The programList table has just two fields in it - userID and programID. Using parameters in my cs file. Here is the complete method:
public void AddProgramList (string program, int userID)
{
dbConnection.Open();
string sqlStmt = "INSERT INTO programs (program) ";
sqlStmt += "VALUES (#program)";
string sqlStmt2 = "INSERT INTO programList (userID, programID) " +
"SELECT userID " +
"FROM users" +
"WHERE userID = #userID " +
"UNION " +
"SELECT programID " +
"FROM programs" +
"WHERE program = #program;";
OleDbCommand dbCommand = new OleDbCommand(sqlStmt, dbConnection);
OleDbParameter param = new OleDbParameter("#program", program);
dbCommand.Parameters.Add(param);
dbCommand.Parameters.Add(new OleDbParameter("#userID", userID));
OleDbCommand dbCommand2 = new OleDbCommand(sqlStmt2, dbConnection);
OleDbParameter param2 = new OleDbParameter("#program", program);
dbCommand2.Parameters.Add(param2);
dbCommand2.Parameters.Add(new OleDbParameter("#userID", userID));
dbCommand.ExecuteNonQuery();
dbCommand2.ExecuteNonQuery();
dbConnection.Close();
}
If you printed out the SQL, you would see:
INSERT INTO programList (userID, programID) " +
SELECT userID FROM usersWHERE userID = #userID UNION SELECT programID FROM programsWHERE program = #program;
The error should be pretty obvious. You probably don't have a table called usersWHERE.
As I look at the problem, you are trying to insert two columns. So, I think you intend:
INSERT INTO programList (userID, programID)
SELECT userID, programID
FROM users, programs
WHERE userID = #userID AND program = #program;
Or, more simply:
INSERT INTO programList (userID, programID)
SELECT #userID, programid
FROM programs
WHERE program = #program;

get last inserted row id in ebean with sqlupdate

If I am using ebean sqlupdate to do insert into Oracle in Java
Transaction tx = Ebean.beginTransaction();
try {
Transaction tx = Ebean.beginTransaction();
try {
String sqlString = "INSERT INTO customers VALUES (1001,'Nichols', 'Alexandra', '17 Maple Drive', "+ "'Nashua', 'NH','03062', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (-71.48923,42.72347,NULL), NULL, NULL))";
SqlUpdate query = Ebean.createSqlUpdate(sqlString);
query.execute();
String sqlQuery =
"SELECT ##IDENTITY AS 'Identity'";
SqlQuery query2 = Ebean.createSqlQuery(sqlQuery);
List<SqlRow> list = query2.findList();
System.out.println(list.get(0));
} finally {
tx.commit();
}
It gives error
[PersistenceException: Query threw SQLException:ORA-00936: missing expression
Query was:
SELECT ##IDENTITY AS 'Identity'
]
How do I get the id of last inserted row?
After an INSERT, SELECT INTO, or bulk copy statement is completed, ##IDENTITY contains the last identity value that is generated by the statement.
But this is in sql So i think you should create the USP and you can return the last inserted record id as outparm from the USP
String sqlString = "INSERT INTO customers VALUES (1001,'Nichols', 'Alexandra', '17 Maple Drive', "+ "'Nashua', 'NH','03062', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (-71.48923,42.72347,NULL), NULL, NULL))";
SqlUpdate query = Ebean.createSqlUpdate(sqlString);
query.execute();
SELECT ##IDENTITY AS 'Identity';

Oledb update sql statement example

con.Open();
cmd = new OleDbCommand("UPDATE staff SET StaffNr = #a, FirstName = #b,
Surname = #c, Email = #d, Balance = #e WHERE Email = #d", con);
cmd.Parameters.AddWithValue("#b", textBoxStaffName.Text);
cmd.Parameters.AddWithValue("#c", textBoxStaffSur.Text);
cmd.Parameters.AddWithValue("#d", textBoxStaffE.Text);
cmd.Parameters.AddWithValue("#e", double.Parse(textBoxSatffBal.Text));
cmd.Parameters.AddWithValue("#a", int.Parse(textBoxStaffNr.Text));
cmd.ExecuteNonQuery();
con.Close();
not updating the database for some reason but the code runs
OldDb uses ? for parameters, not #x. You have to add parameters in order. The name is ignored in AddWithValue (this method comes from a general purpose superclass)
con.Open();
cmd = new OleDbCommand("Update staff set StaffNr = ?, FirstName = ?,
Surname = ?, Balance = ? Where Email = ?", con);
cmd.Parameters.AddWithValue("#a", int.Parse(textBoxStaffNr.Text));
cmd.Parameters.AddWithValue("#b", textBoxStaffName.Text);
cmd.Parameters.AddWithValue("#c", textBoxStaffSur.Text);
cmd.Parameters.AddWithValue("#e", double.Parse(textBoxSatffBal.Text));
cmd.Parameters.AddWithValue("#d", textBoxStaffE.Text);
cmd.ExecuteNonQuery();
con.Close();

Returning multiple values from a stored procedure

I am using SQL Server. I am calling a stored procedure from another stored procedure.
I want to return multiple values from the first stored procedure.
Ex: I am calling Sub_SP from Master_SP. Sub_SP will return multiple values to Master_SP.
Can anyone give an example with OUTPUT parameters?
Thank you.
ALTER procedure ashwin #empid int,#empname varchar(20) output,#age int output
as
select #empname=ename,#age=age
from emp where empid=#empid;
declare #ename varchar(20),#age int
execute ashwin 101,#ename out,#age out
select #ename,#age;
//------------
namespace sqlserver
{
class Program
{
static void Main(string[] args)
{
createconnection();
}
public static void createconnection()
{
SqlConnection con=new SqlConnection("Data Source=ASHWIN\\SQLEXPRESS;Initial Catalog=employee;Integrated Security=True;Pooling=False");
con.Open();
SqlCommand cmd=new SqlCommand("ashwin",con);
cmd.CommandType=CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#empid",SqlDbType.Int,10,"empid"));
cmd.Parameters.Add(new SqlParameter("#empname", SqlDbType.VarChar, 20,ParameterDirection.Output,false,0,20,"ename",DataRowVersion.Default,null));
cmd.Parameters.Add(new SqlParameter("#age", SqlDbType.Int, 20, ParameterDirection.Output, false, 0, 10, "age", DataRowVersion.Default, null));
cmd.Parameters[0].Value = 101;
cmd.UpdatedRowSource = UpdateRowSource.OutputParameters;
cmd.ExecuteNonQuery();
string name = (string)cmd.Parameters["#empname"].Value;
int age = Convert.ToInt32(cmd.Parameters["#age"].Value);
Console.WriteLine("the name is {0}--and age is {1}", name,age);
Console.ReadLine();
}
}
How about this:
CREATE PROCEDURE dbo.SubSP
#Value1 INT OUTPUT, #Value2 INT OUTPUT
AS
-- just return two values into the OUTPUT parameters somehow....
SELECT #Value1 = 42, #Value2 = 4711
Test the dbo.SubSP:
DECLARE #Out1 INT, #Out2 INT
EXEC dbo.SubSP #Out1 OUTPUT, #Out2 OUTPUT -- int
SELECT #Out1, #Out2
Gives output:
#Out1 #Out2
42 4711
Then create "master" stored procedure:
CREATE PROCEDURE dbo.MasterSP
#SomeValue1 INT OUTPUT, #SomeValue2 INT OUTPUT, #SomeValue3 INT OUTPUT
AS BEGIN
DECLARE #Out1 INT, #Out2 INT
-- call the "sub" stored procedure and capture OUTPUT values
EXEC dbo.SubSP #Out1 OUTPUT, #Out2 OUTPUT
-- return those values - plus some others - from master stored procedure
SELECT #SomeVAlue1 = #Out1, #SomeVAlue2 = #Out2, #SomeValue3 = 9901
END
Test master stored proc:
DECLARE #Some1 INT, #Some2 INT, #Some3 INT
EXECUTE dbo.MasterSP #Some1 OUTPUT, #Some2 OUTPUT, #Some3 OUTPUT
SELECT #Some1, #Some2, #Some3
Gives output:
(No column name) (No column name) (No column name)
42 4711 9901
Does this work? Does this solve your problem? If not: where are you stuck, what exactly is the problem?
I had the same problem and I am working in VB. I have tried the #Scorpian275 's answer. This is the same solution as #Scorpian275 provided but it is for the VB. The sql part is the same.
Public Shared Sub createConnection()
Dim con As SqlConnection = New SqlConnection("Data Source=ASHWIN\\SQLEXPRESS;Initial Catalog=employee;Integrated Security=True;Pooling=False")
con.Open
Dim cmd As SqlCommand = New SqlCommand("ashwin", con)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add(New SqlParameter("#empid", SqlDbType.Int, 10, "empid"))
cmd.Parameters.Add(New SqlParameter("#empname", SqlDbType.VarChar, 20, ParameterDirection.Output, false, 0, 20, "ename", DataRowVersion.Default, Nothing))
cmd.Parameters.Add(New SqlParameter("#age", SqlDbType.Int, 20, ParameterDirection.Output, false, 0, 10, "age", DataRowVersion.Default, Nothing))
cmd.Parameters(0).Value = 101
cmd.UpdatedRowSource = UpdateRowSource.OutputParameters
cmd.ExecuteNonQuery
Dim name As String = CType(cmd.Parameters("#empname").Value,String)
Dim age As Integer = Convert.ToInt32(cmd.Parameters("#age").Value)
Console.WriteLine("the name is {0}--and age is {1}", name, age)
Console.ReadLine
End Sub
The last parameter in
cmd.Parameters.Add(New SqlParameter("#age", SqlDbType.Int, 20, ParameterDirection.Output, false, 0, 10, "age", DataRowVersion.Default, Nothing))
is the initial value that we provide for those variables (Here Nothing).

SQL Server 2005 CE 3.5 Re seed IDENTITY

I have inserted some rows into a data table with
Set Identity_insert tblEvent on
I then attempt to 'reseed' the Identity field
int MaxId = this.MaxID()+1;
string upgrade = "ALTER TABLE " + Table + " ALTER COLUMN ID IDENTITY("+ MaxId.ToString() +",1)";
System.Data.SqlServerCe.SqlCeCommand cmd = new System.Data.SqlServerCe.SqlCeCommand(upgrade, connection);
cmd.CommandType = System.Data.CommandType.Text;
connection.Open();
cmd.ExecuteNonQuery();
connection.Close();
'MaxId' is determined by
int MaxId = 0;
string upgrade = "select Max(ID) from " + Table;
System.Data.SqlServerCe.SqlCeCommand cmd = new System.Data.SqlServerCe.SqlCeCommand(upgrade, connection);
cmd.CommandType = System.Data.CommandType.Text;
connection.Open();
MaxId = (int)cmd.ExecuteScalar();
connection.Close();
return MaxId;
However, if I query Max(ID) again after seeding it has'nt changed
Any idea's aprreciated
Try this:
string upgrade = " DBCC CHECKIDENT('[" + Table + "]', RESEED, " + (MaxId + 1)+ " )"
weird, could it be a permissions issue. you should have seen an exception though, unless the exception is gobbled up by a catch all.