Inserting to one table, insert the ID to second table - sql

Is it possible to populate a second table when I insert into the first table?
Insert post to table1 -> table 2 column recieves table1 post's unique id.
What I got so far, am I on the right track?
CONSTRAINT [FK_dbo.Statistics_dbo.News_News_NewsID] FOREIGN KEY ([News_NewsID]) REFERENCES [dbo].[News] ([NewsID])

Lots of ways:
an insert trigger
read SCOPE_IDENTITY() after the first insert, and use it to do a second
use the output clause to do an insert
Examples:
1:
create trigger Foo_Insert on Foo after insert
as
begin
set nocount on
insert Bar(fooid)
select id from inserted
end
go
insert Foo (Name)
values ('abc');
2:
insert Foo (Name)
values ('abc');
declare #id int = SCOPE_IDENTITY();
insert Bar(fooid)
select #id
3:
insert Bar(fooid)
select id from (
insert Foo (Name)
output inserted.id
values ('abc')) x

The only thing I can think of is that you can use a trigger to accomplish this. There is nothing "built in" to SQL Server that would do it. Why not just do it from your .NET code?

Yes it is, it sounds like you want a SQL Trigger, this would allow you to trigger logic based on actions on one table, to perform other actions in the DB. Here's another article on creating Simple SQL Triggers
SQL Server 2008 - Help writing simple INSERT Trigger
A Word of caution, this will do all the logic of updating the new table, outside of any C# code you write, it might sound nice to not have to manage it upfront, but you also lose control over when and if it happens.
So if you need to do something different later, now you have to update your regular code, as well as the trigger code. This type of logic can definitely grow, in large systems, and become a nightmare to maintain. Consider this, the alternative would be to build a method that adds the id to the new table after it inserts into the first table.
While i don't know what you're using to do your inserts assuming it's a SQL Command you can get back the ID on an identity column from the insert using Scope_Identity, found here
How to insert a record and return the newly created ID using a single SqlCommand?
if it's EF or some other ORM tool, they should either automatically update the entity, or have other mechanisms to deliver this data.

Related

How to write a stored procedure to insert values into two tables with a foreign key relationship?

I created two tables, Employeeinfo and Employeerequests.
Table Employeeinfo can have one unique user with columns:
id (primary key, auto increment)
name
dep
address
and table Employeerequests can have multiple requests against one unique user ID with columns
id (primary key, auto increment)
CustomerID(foreign key to Employeeinfo(ID column))
category
requests.
Now I want to design a stored procedure in such a way so that I can insert values into both tables at the same time. Please help. I am very new to SQL. Thanks in advance.
This is a bit long for a comment.
SQL Server only allows you to insert into one table in a single query. You presumably want to provide both employee and request information. So that limitation on insert is a real problem.
You can get around the limitation by creating a view combining the two table and then defining an instead of insert trigger on the view. This is explained in the documentation.
That said, you seem to not have extensive SQL knowledge. So, I would recommend simply using two separate statements, one for each table. You can wrap them in a stored procedure, if you find that convenient.
In the stored procedure, you can use Output clause of Insert statement as:
DECLARE #MyTableVar TABLE (NewCustomerID INT);
-- The OUTPUT clause have access to all the columns in the table,
-- even those not part of Insert statement ex:EmployeeID.
INSERT INTO [dbo].[Employeeinfo] ([Name], [dep], [address])
OUTPUT INSERTED.Id INTO #MyTableVar
SELECT 'Test', 'TestDep', 'TestAddress'
-- then make insert in child table as
INSERT INTO [dbo].[Employeerequests] (CustomerID, category)
SELECT NewCustomerID, 'TestCat'
FROM #MyTableVar
Sample code here...
Hope that helps!

How to insert into the table a user name record

I've a table. In this table I have two columns - 'insert_name' and 'modified_name'. I need to insert into this columns data about who has inserted data into the table('insert_name') and who has changed these data in the table (modified_name). How it can be done?
You are looking for basic DML statements.
If your record is already in the table, then you need to UPDATE it. Otherwise, when you are about to add your record to it and it doesn't already exist in the destination table then you are looking for INSERT INTO statement.
Example of updating information for record with first id:
UPDATE yourtable SET insert_name = 'value1', modified_name = 'value2' WHERE id = 1
Example of inserting new record:
INSERT INTO yourtable(id, company_name, product_name, insert_name)
VALUES (1, 'Google', 'PC', 'value1')
If you are looking for automatic changes to those columns then you need to look into triggers.
Remember that more often than not you may find that the application connecting to the database is using single database user in which case you probably know the context within the application itself (who inserts, who updates). This does eliminate triggers and put the task straight on simple insert/update commands from within your application layer.
You might be able to use the CURRENT_USER function to find the name of the user making the change.
The value from this function could then be used to update the appropriate column. This update could be done as part of the INSERT or UPDATE statement. Alternatively use an INSERT or UPDATE trigger.
Personally I avoid triggers if I can.
For those 2 columns add Current_User as Default constraint.
As the first time Insert Statement will save them with current login user names. For update write an Update trigger with the same Current_User statement for the column Modified_Name.
If and only if your application business logic can't update the column modified_nme then only go for Trigger.
See the use of Current_Use
https://msdn.microsoft.com/en-us/library/ms176050.aspx

Is is safe to use ##IDENTITY in a transaction?

I was reading this answer about different methods of getting the last identity value entered into a database.
From what I understand, ##IDENTITY is usually a very bad idea because it might return an identity that is not the one you expected--for example an identity value that was recently created by a trigger.
But what if your code is in a transaction?
For example this is a simplified version of a transaction I'm doing (using ColdFusion):
<cftransaction>
<cfquery name="queryInsertA" datasource="source">
INSERT INTO tableA (columnName) VALUES (value)
</cfquery>
<cfquery name="queryInsertB" datasource="source">
INSERT INTO tableB (fkey_tableA, columnName) VALUES (##IDENTITY, value)
</cfquery>
</cftransaction>
Since, "If a transaction is successful, all of the data modifications made during the transaction are committed and become a permanent part of the database," does this mean that it would also prevent the isses that can arise when using ##IDENTITY? Or am I misunderstanding the behavior of transactions?
The answer you linked already explains what the main issue is with ##IDENTITY: scope. If your insert triggers another insert, you get an unexpected identity back. Transactions do not change anything.
If you wanted to get the last identity value inserted to a table, use the Ident_current() function.
Select ident_current ('your table name')
Also you can use scope_identity(), It will bring the identity value of a tablein that particular scope only.
Select scope_identity()
You don't need ##Identity, nor do you need 2 separate queries. Use the Scope_identity() function for integrity and make it a part of the same connection & query - like so.
<cfquery name="putUser" datasource="#dsn#">
SET NOCOUNT ON
INSERT INTO users(username, email)
VALUES
('#usersname#','#email#' )
SELECT SCOPE_IDENTITY() AS newId FROM users
SET NOCOUNT OFF
</cfquery>
<cfoutput>#putUser.newID#</cfoutput>
This will be totally safe, but like all db transactions it will still be subject to deadlocks so tuning is still important.
CFTRANSACTION is good for multiple DB operations where some CF logic might also be involved, but let the DB locking and transactional system work for you by keeping it together.
You can also use the result attribute of cfquery. If the query performs an INSERT of an identity or auto-increment value for ID, there will be a key named GENERATEDKEY returned in the structure.
<cftransaction>
<cfquery name="queryInsertA" datasource="source" result="resultA">
INSERT INTO tableA (columnName) VALUES (value)
</cfquery>
<cfquery name="queryInsertB" datasource="source">
INSERT INTO tableB (fkey_tableA, columnName) VALUES (#resultA.generatedKey#, value)
</cfquery>
</cftransaction>
Keep in mind this is only CF9 and higher.
You can use Sequence and use that during insert as below:
CREATE SEQUENCE Testseq
START WITH 1
INCREMENT BY 1 ;
Access the sequence by using below query:
SELECT NEXT VALUE FOR Testseq;
To make it simple :
IF
You know you'r ALL ALONE in the db system, this means, no other user, or process running at the same time, no other transaction running, there is absolutly ZERO activity at the time you use it, and i mean it, ZERO ACTIVITY, then, ok...
ELSE
NO ! If anything like i listed above does occur exactly while your transact is running, you will end up with the wrong identity.
It depends on what else is running at the same time as your transaction is instantiated. If there is a trigger on a table unrelated to the transaction that can insert a new identity value, the transaction scope you are currently in will not protect you.
For example say I create a SPROC that updates Table_A and inserts a record into it. This table has an identity field on it that will increment the ID value in that table each time a new record is inserted. Inside my SPROC I create a transaction and place my insert inside the transaction. After the insert I store the value of ##IDENTITY in a variable inside the same transaction.
Now I also have another table Table_B with it's own identity value but this table is trigger maintained. If I am executing my SPROC to insert a row in Table_A and during this update Table_B is also updated via a trigger, it is possible that when I retrieve the value of ##IDENTITY, it will actually give me the value of the ID created for Table_B rather than Table_A.
You should definitely use Transactions in your stored procedures but you are better off selecting the MAX(ID) of the table you inserted into to retrieve the ID you created rather than ##IDENTITY.

insert data in multiple tables

hi i have a problem to insert data in multiple tables. i have define primary key & reference key in tables now i want to insert data in both tables in single query.......how can i do this...........???????
Your question isn't exactly clear on what the particular problem is. I can see three possibilities:
1. You want to insert into two tables wiht a single INSERT statement
2. You want to do two inserts, but without anything else being able to 'get in the middle'
3. You want to insert into one table, then get the primary key to insert into the second table
The answer to 1. is simple:
You can't.
The answer to 2. is simple too:
BEGIN TRANSACTION
INSERT INTO <table1> (a,b,c) VALUES (1,2,3)
INSERT INTO <table2> (a,b,c) VALUES (1,2,3)
COMMIT TRANSACTION
The answer to 3. is has several possibilities. Each depending on exactly what you want to do. Most likely you want to use SCOPE_IDENTITY() but you may also want to look up ##identity and IDENT_CURRENT() to understand the various different options and complexities.
BEGIN TRANSACTION
INSERT INTO <dimension_table> (name)
VALUES ('my new item')
INSERT INTO <fact_table> (item_id, iteam_value)
VALUES (SCOPE_IDENTITY(), 1)
COMMIT TRANSACTION
This is what transactions are meant for. Standard SQL does not permit a single statement inserting into multiple tables at once. The correct way to do it is:
-- begin transaction
insert into table 1 ...
insert into table 2 ...
commit
Does your language support the INSERT ALL construct? If so, that is the best way to do this. In fact it's the only way. I posted an example of this construct in another SO thread (that example syntax comes from Oracle SQL).
The other option is to build a transactional stored procedure which inserts a record into the primary key table followed by a record into the referencing table.
And 1 of your choice to do that is use ORM (like Hibernate, NHibernate) the you make your object and set other relation to it and finally just save the main object , like:
A a;
B b;
C c;
a.set(b);
a.set(c);
DAO.saveOrUpdate(a);
you must notice your DAO.saveOrUpdate(a); line of code just work with hibernate but it insert data into 3 table A, B, C.

Trigger event is fired only once for Microsoft SQL Server 2005 DB if more than one rows updated?

I have a table MyTable with a trigger defined like this:
ALTER TRIGGER [MyTableInsertDeleteUpdate]
ON [dbo].[MyTable]
AFTER INSERT,DELETE,UPDATE
AS
DECLARE #id int;
BEGIN
SELECT #id = ins.id FROM inserted ins;
IF (#id IS NOT NULL)
BEGIN
-- insert a new record to audit table
PRINT 'inserted/updated id: ' + CAST(#id AS VARCHAR);
END
END
I realize that if more than one rows are updated like this,
UPDATE MyTable SET name = 'test rows' WHERE id in (1, 2, 3);
the tigger is called only once and only the firstone in [inserted] is updated. Actually, [inserted] may have more than one rows (3 in this case if id 1, 2,3 exist). In order words, the trigger is not fired on each row. Is that right?
I am using Microsoft SQL Server 2005.
Yeah the trigger is fired once per statement (not once per row) that makes the changes you are subscripting to. It will even fire if no rows where affected.
http://msdn.microsoft.com/en-us/library/ms189799(SQL.90).aspx
As Hojou said, your trigger will fire once per statement rather than once per affected row. This is different to databases like Interbase and Firebird, and threw me when I first started using SQL Server.
The whole point of the inserted and deleted 'virtual' tables is because the events are record-SET based, not row-based.
There are any number of tutorials out there that cover writing sql to process the inserted/deleted tables, but watch out for the shovelware ones. I've seen more than a couple of so-called tutorials that have just been copy/pasted from another database platform and won't actually work in SQL Server as they claim to (one of the top hits for 'SQL Server trigger example' in Google gets it completely wrong for UPDATE statements).
This is a reasonable introduction to Triggers and the concepts required to make sense of the inserted and deleted tables, with an explanation of why you will be missing events in your own example. The Microsoft docs themselves are reasonably useful once you get past their dull, lifeless structure and writing-style.
To insert records to an audit table from an insert you would do something like this in the trigger:
insert auditable (field1, field2, insert_date, insertedBy)
select field1, field2, getdate(), user_Name() from inserted
No fooling around with setting variables just a a plain insert based on a select statment.
Personally I would have a separate trigger for inserts, updates and deletes as you want differnt code for each.