Microsoft SQL server: have one auto-incrementing column update another table - sql-server

I have a table of orders with orderID. I want when I create a new row in orders, and automatically have it add the same orderID to a new row in orderDetails. I got the auto incrementing to work, however whenever I try to link the two, adding cascade delete, it gives me an error.
'order' table saved successfully
'orderDetail' table
- Unable to create relationship 'FK_orderDetail_order'.
Cascading foreign key 'FK_orderDetail_order' cannot be created where the referencing column 'orderDetail.orderID' is an identity column.
Could not create constraint. See previous errors.
Which seems to be because of the fact there is no orderID at row creation. Without these two linked it's pretty hard to link an order to its information.
I am using Microsoft SQL server mgt studio. I learned via command-line MySQL, not SQL, so this whole GUI stuff is throwing me off (and I'm a tad rusty).

Your problem is that 'orderDetail.orderID' should not be an identity column (auto-incrementing). It should be based on the orderId in the Order table. You can do that in a variety of ways. If you are using stored procedures, and making separate calls to the database for the orderDetail records, have the code save the order row first, and return the newly created OrderId value, then use that value on the calls to save orderdetails. If you are making one call to a stored proc that saves the order header record and all order detail records in one call, then in the stored procd, insert the ordfer record forst, use Scope_identity() to extract the newly created orderId into a T-SQL variable,
Declare #orderId Integer
Insert Orders([Order table columns])
Values([Order table column values])
Set #orderId = scope_Identity()
and then use the value in #orderId for all inserts into the OrderDetails table...
Insert OrderDetails(OrderId, [Other OrderDetail table columns])
Values(#orderId , [Other OrderDetail table column values])

You want a AFTER INSERT trigger on the order table - in this, the newly given ID is available as NEW.orderID and can now easily be inserted into orderDetails.
Just do this via the command line. I certainly do.

Related

SQL Insert does column order matter

I have two tables with the same field names and a stored procedure that updates table B with Table A's data by doing a delete from current table and insert into current table from another table that has update values in it:
delete from ac.Table1
insert into ac.Table1
select *
from dbo.OriginalTable
where dtcreate <getdate()-1
I had to recreate Table1 through GIS software which adds GlobalIDs and an Object ID field. The original order had Object ID at the end and the new table has it at the front. Will this impact executing the SQL statement above?
Yes it will. The order of the columns should match for each value to go in desired column
You can try
Insert into ac.Table1 (column1....columnN)

Script out objects from DB with identity columns replaced by variables to copy object to other environment

I have multiple environments for an application, like DEV, TEST, UAT, PROD.
I would need to copy some objects from the database created in UAT environment into PROD environment. The object is stored in the DB spreaded to multiple tables. Most of the tables have PK as IDENTITY (autogenerated). I don't have access to PROD db data (it is sensitive data in general).
What I need is to generate SQL script for inserting the object that does not preserve the values of Ids but uses the Ids assigned in target environment to related records.
Example: let's say object Order composed of [Order] and list of [OrderItem] rows. I would need to select one specific row in [Order] table, specify that also related rows from [OrderItem] should be included and generate script that would insert new row for [Order], get the value of assigned Order.Id, keep it in a variable and use it for inserting [OrderItem] rows. This is trivial example, my object is spreaded to many more tables, but the concept is the same.
Is there any tool for doing this? All scripting out utilities I tried preserve values of Identity columns.
I think you would need to write custom code to achieve the need of first loading to parent table, followed by loading to child table based on SCOPE_IDENTITY() value.
Instead, if you don't have huge number of rows, I would suggest you to follow below steps:
Load data from Production to another environment using SSIS package or another means
Add the foreign key constraint in the child table to have UPDATE CASCADE
ALTER TABLE ChildTable ADD CONSTRAINT FK_OrderDetail_Order FOREIGN KEY([OrderID])
REFERENCES [dbo].[Order] ([OrderID])
ON UPDATE CASCADE
Now, Update the identity value to another value using some logic
set identity_insert Order ON
UPDATE Order SET OrderID = OrderID + 1000000 -- Have some other logic for random generation
set identity_Insert Order OFF
Now, automatically the child table will get updated with new OrderID.
UPDATE
This SO link talks about automating the code generation for INSERT scripts: What is the best way to auto-generate INSERT statements for a SQL Server table?
Also, I would suggest you to first script out parent tables, followed by child tables.
You can identify parent,child tables using the below script. You need to generate scripts now as per the parent, child depency.
select object_name(parent_object_id) as childTable, object_name(referenced_object_id) as parentTable
from sys.foreign_keys
WHERE object_name(parent_object_id) IN 'Your comma separated list of tables'

How To change the column order of An Existing Table in SQL Server 2008

I have situation where I need to change the order of the columns/adding new columns for existing Table in SQL Server 2008.
Existing column
MemberName
MemberAddress
Member_ID(pk)
and I want this order
Member_ID(pk)
MemberName
MemberAddress
I got the answer for the same ,
Go on SQL Server → Tools → Options → Designers → Table and Database Designers and unselect Prevent saving changes that require table re-creation
2- Open table design view and that scroll your column up and down and save your changes.
It is not possible with ALTER statement. If you wish to have the columns in a specific order, you will have to create a newtable, use INSERT INTO newtable (col-x,col-a,col-b) SELECT col-x,col-a,col-b FROM oldtable to transfer the data from the oldtable to the newtable, delete the oldtable and rename the newtable to the oldtable name.
This is not necessarily recommended because it does not matter which order the columns are in the database table. When you use a SELECT statement, you can name the columns and have them returned to you in the order that you desire.
If your table doesn't have any records you can just drop then create your table.
If it has records you can do it using your SQL Server Management Studio.
Just click your table > right click > click Design then you can now arrange the order of the columns by dragging the fields on the order that you want then click save.
Best Regards
I tried this and dont see any way of doing it.
here is my approach for it.
Right click on table and Script table for Create and have this on
one of the SQL Query window,
EXEC sp_rename 'Employee', 'Employee1' -- Original table name is Employee
Execute the Employee create script, make sure you arrange the columns in the way you need.
INSERT INTO TABLE2 SELECT * FROM TABLE1.
-- Insert into Employee select Name, Company from Employee1
DROP table Employee1.
Relying on column order is generally a bad idea in SQL. SQL is based on Relational theory where order is never guaranteed - by design. You should treat all your columns and rows as having no order and then change your queries to provide the correct results:
For Columns:
Try not to use SELECT *, but instead specify the order of columns in the select list as in: SELECT Member_ID, MemberName, MemberAddress from TableName. This will guarantee order and will ease maintenance if columns get added.
For Rows:
Row order in your result set is only guaranteed if you specify the ORDER BY clause.
If no ORDER BY clause is specified the result set may differ as the Query Plan might differ or the database pages might have changed.
Hope this helps...
This can be an issue when using Source Control and automated deployments to a shared development environment. Where I work we have a very large sample DB on our development tier to work with (a subset of our production data).
Recently I did some work to remove one column from a table and then add some extra ones on the end. I then had to undo my column removal so I re-added it on the end which means the table and all references are correct in the environment but the Source Control automated deployment will no longer work because it complains about the table definition changing.
The real problem here is that the table + indexes are ~120GB and the environment only has ~60GB free so I'll need to either:
a) Rename the existing columns which are in the wrong order, add new columns in the right order, update the data then drop the old columns
OR
b) Rename the table, create a new table with the correct order, insert to the new table from the old and delete from the old as I go along
The SSMS/TFS Schema compare option of using a temp table won't work because there isn't enough room on disc to do it.
I'm not trying to say this is the best way to go about things or that column order really matters, just that I have a scenario where it is an issue and I'm sharing the options I've thought of to fix the issue
SQL query to change the id column into first:
ALTER TABLE `student` CHANGE `id` `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT FIRST;
or by using:
ALTER TABLE `student` CHANGE `id` `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT AFTER 'column_name'

Stored procedure to generate a unique id column

Good day
I have a situation where two users are saving data to the same database and there are primary key conflicts.
Is it possible to write a stored procedure or trigger which will generate a unique identity by adding two columns.
For instance: I have table2 related to table1 by Table1ID. Increment and seed is 1 for both.
If I had to add a row to table2 I would like the autogenerated ID number to be added to a text column thereby making it unique. So the ID would be something like JoeSoap5.
If you want to generated something unique you can use the build-in function "NEWID()". Type and executed the following code:
SELECT NEWID()
If you need to insert record in second table when record in your first table is inserted, is is possible to implement this using TRIGGERS. In your case you can use "AFTER INSERT TRIGGER" or "BEFORE INSERT TRIGGER" - generally this will be a piece of code that will be executed AFTER/BEFORE row in your first table is inserted.
You don't specify your SQL Server version.
SQL 2012 introduces the concept of a sequence - http://msdn.microsoft.com/en-us/library/ff878091.aspx - which would allow you to do just what you want.

Best way to move data between tables and generate mapping of old to new identity values

I need to merge data from 2 tables into a third (all having the same schema) and generate a mapping of old identity values to new ones. The obvious approach is to loop through the source tables using a cursor, inserting the old and new identity values along the way. Is there a better (possibly set-oriented) way to do this?
UPDATE: One additional bit of info: the destination table already has data.
Create your mapping table with an IDENTITY column for the new ID. Insert from your source tables into this table, creating your mapping.
SET IDENTITY_INSERT ON for your target table.
Insert into the target table from your source tables joined to the mapping table, then SET IDENTITY_INSERT OFF.
I created a mapping table based on the OUTPUT clause of the MERGE statement. No IDENTITY_INSERT required.
In the example below, there is RecordImportQueue and RecordDataImportQueue, and RecordDataImportQueue.RecordID is a FK to RecordImportQueue.RecordID. The data in these staging tables needs to go to Record and RecordData, and FK must be preserved.
RecordImportQueue to Record is done using a MERGE statement, producing a mapping table from its OUTPUT, and RecordDataImportQueue goes to RecordData using an INSERT from a SELECT of the source table joined to the mapping table.
DECLARE #MappingTable table ([NewRecordID] [bigint],[OldRecordID] [bigint])
MERGE [dbo].[Record] AS target
USING (SELECT [InstanceID]
,RecordID AS RecordID_Original
,[Status]
FROM [RecordImportQueue]
) AS source
ON (target.RecordID = NULL) -- can never match as RecordID is IDENTITY NOT NULL.
WHEN NOT MATCHED THEN
INSERT ([InstanceID],[Status])
VALUES (source.[InstanceID],source.[Status])
OUTPUT inserted.RecordID, source.RecordID_Original INTO #MappingTable;
After that, you can insert the records in a referencing table as folows:
INSERT INTO [dbo].[RecordData]
([InstanceID]
,[RecordID]
,[Status])
SELECT [InstanceID]
,mt.NewRecordID -- the new RecordID from the mappingtable
,[Status]
FROM [dbo].[RecordDataImportQueue] AS rdiq
JOIN #MappingTable AS mt
ON rdiq.RecordID = mt.OldRecordID
Although long after the original post, I hope this can help other people, and I'm curious for any feedback.
I think I would temporarily add an extra column to the new table to hold the old ID. Once your inserts are complete, you can extract the mapping into another table and drop the column.

Resources