I need to make a copy of a row in a table and also copy all the rows that link to it via its foreign key in other tables. And then copy all the rows that link to these rows.
The problem is when I make a copy of the row the key is going to change. How can I propagate these changes through the relationships between tables?
You can write a stored procedure which implements all the copy logic.
Essentially:
Insert copy row in master table -
store new ID in variable
Insert
copy of each row in child tables,
referencing FK in variable. Store the ID of the child row in variable2
Insert new rows in tables dependent upon the child table, referencing the FK in variable2.
In short, write a stored proc that starts at the top and walks down as many tables as needed.
A bit of a 'hack', but I often add a column 'copy_of_id', so that I can store the old id, and then copy over all rows in dependent tables for the newly created value.
It ain't pretty, but has advantages (human tracebility of what's happening, for instance).
You can also use a helper table for this, of course. Containing old ID and new ID columns. That will not pollute your primary table.
When creating your new "parent row", ##IDENTITY and SCOPE_IDENTITY() will contain the Id of your new header.
Then you can use them to create your "child rows", such as
INSERT INTO parent_table (parent_field1, parentfield2) VALUES('Some stuff', 'Other stuff');
INSERT INTO child_table (parent_id, other_field) VALUES(SCOPE_IDENTITY(), 'Etc.')
Take a look on MSDN for ##IDENTITY and SCOPE_IDENTITY() for code examples.
Related
I have two tables, "table1" and "table2". They contain rows that are related to each other. The table "table2" has pairs of rows with a column named "table1_id" and these pairs refer to the sequential "id" columns in "table1".
The task that needs to be performed is that I need to copy rows from both tables and put these rows into the same tables with new data while maintaining the relationships between them.
I have read several posts on StackOverflow and some articles on "mssqltips.com", but I am still not sure how I should do this. Should I use a cursor or a query with joins and a temporary table? What is the best-practice way to achieve the above task and if possible, could you demonstrate a short example?
You cannot "copy both rows from both tables and put these into the same tables" verbatim if the id column is being copied and is truly an ID (a unique key). If you want to duplicate some other (non-key) columns into new rows with new IDs, that's fine. If that's what you want, you can create the primary key (table1) row(s) first, and reference the newly created keys. How you do this depends on whether the id column is a generated or explicitly specified key, and whether you have any keys (primary or foreign keys) in table2 as well.
It might look something like this:
insert into table1
select col1, col2, etc
from table1
where id = 'somekey'
insert into table2
select 'newkey' as table1_id, col3, col4, etc
from table2
where table1_id = 'somekey'
If you want to do this atomically, wrap it in a begin transaction, and make use of an OUTPUT clause or similar to collect the new IDs; see the documentation about that.
I do not know if my request has a name but I think it can be called "duplicating a row with all the rows below it in the hierarchy tables".
I want to create a stored procedure that can duplicate a record and all its childs and grandchilds records.
When I say "Duplicate" I main that all the record values in the columns will be copy to a new record on the same table (the copy should be without Primary key Id column because its automated)
This Stored Procedure needs to get two parameters:
Parameter 1 - Table Name
Parameter 2 - Value of the Primary key Id (of that Table Name) that needs to duplicate.
Instructions of the code:
The value (Parameter 2) will find one record on the table (Parameter 1) and duplicate it (as I said same values for all the columns excluding the primary key of that table.
Then we will need to know all the table names that has a relationship with this primary key (of the parent table)
Then every child table will duplicate the records that have the same Id value (Parameter 2) with the new Id value (of the new parent record).
several things:
In the dream scenario the code knows to go down levels without any limit (children, grandchildren, great-grandchildren ...) ,but I guess it is a very complex code that will contain some recursion code, so even a code containing up to 3-4 levels I will be happily accepted.
I am planning for an incremental load into warehouse (especially for updates of source tables in RDBMS).
Capturing the updated rows in staging tables from RDBMS based the updates datetime. But how do I determine which column of a particular row needs to be updated in the target warehouse tables?
Or do I just delete a particular row in the warehouse table (based on the primary key of the row in staging table) and insert the new updated row?
Which is the best way to implement the incremental load between the RDBMS and Warehouse using PL/SQL and SQL coding?
In my opinion, the easiest way to accomplish this is as follows:
Create a stage table identical to your host table. When you do your incremental/net-change load, load all changed records into this table (based on whatever your "last updated" field is)
Delete the records from your actual table based on the primary key. For example, if your primary key is customer, part, the query might look like this:
delete from main_table m
where exists (
select null
from stage_table s
where
m.customer = s.customer and
m.part = s.part
);
Insert the records from the stage to the main table.
You could also do an update existing records / insert new records, but either way that's two steps. The advantage of the method I listed is that it will work even if your tables have partitions and the newly updated data violates one of the original partition rules, whereas an update would not accomplish that. Also, the syntax is much simpler as your update would have to list every single field, whereas the delete from / insert into allows you list only the primary key fields.
Oracle also has a merge clause that will update if it exists or insert if it does not. I honestly don't know how that would be impacted if you had partitions.
One major caveat. If your updates include deletes -- records that need to be deleted from the main table, none of these will resolve that and you will need some other way to handle that. It may not be necessary, depending on your circumstances, but it's something to consider.
This is my first post, so please excuse me for any obvious or simple questions as I am very new to programming and all my projects are a first to me.
I am currently working on my first database project. A relational database using Oracle sql. I'm new on my course, so I am not sure on all the concepts yet, but working at it.
I have used some modelling software to help me construct a 13 table database. I have setup all my columns and assigned primary and foreign keys to all 13 tables. What I am looking to do now is insert 10 rows of test data into each table. I have done the parent tables but am confused about the child tables. When I assign ID numbers to all the parent tables primary keys, will the child tables foreign keys be populated at the same time?
I have not used sequences yet as I'm not 100% how to make them work, but instead inputted my own values like 100, 101, 102 etc. I know those values need to be in the foreign key, but wouldn't manually inserting them into many tables get confusing?
Is there an easier approach to this or am I over complicating the process?
I will need to use some queries later but I just want to be happy that the data is sound.
Thanks for your help
Rob
No, the child table data won't be populated automatically-- if there is a child table, that implies that there is a 0 or 1 to m relationship between the two. One row in the parent table may have 0 rows in the child table or it may have dozens so nothing could possibly be populated automatically.
If you are manually assigning primary key values, you'd need to hard code those same values as the foreign key values when you insert data into the child tables. In the real world, you wouldn't manually insert data into many tables at once, you'd have an application that did so and that knew what keys to use based on parameters passed in or by getting the currval of the sequence used to populate the primary key after inserting into the parent table.
Its necessary that data for foreign key should be present in parent table, but not the other way around.
If you want to create test data, i suggest you use something like below query.
insert into child_table(fk_column,column1,column2....)
select pk_column,'#dummy_value1#','#dummy_value2#',..
from parent_table
if you have 10 rows in parent, this will add 10 rows in child.
If you want more rows, e.g. 100 for each parent value you need to duplicate the parent data. for that use below query.
insert into child_table(fk_column,column1,column2....)
select pk_column,'#dummy_value1#','#dummy_value2#',..
from parent_table
join (select level from dual connect by level<10)
this will add 100 child values for 10 parent values..
suppose I have three tables (table1, table2, table3) linked to a master table tableM.
I have primary key ID in the tableM and foreign key ID in other tables.
suppose I insert a row in tableM, will other tables get inserted a row automatically? Or do I have to write a sp by my own?
Thanks for any advice!
Rows do not get inserted automatically. You have to insert a row into your master table first, and then insert rows into your FK tables afterwards to avoid a FK constraint error.
No, rows are not inserted automatically. Additionally, the INSERT statement could not possibly include columns from these child tables, so even if a row were inserted automatically it could not include data.
You will need to either write a stored procedure (recommended if these child rows are required by the business logic) or simply insert into tables as necessary.