How to compare data in table (before and after an operation)? - sql

Is there any free tool or a way to get to know what has changed in database's table?

You could take a copy before the update
CREATE TABLE t2 AS SELECT * FROM t1
Run your update
Then to show the differences
use this to show updates:
SELECT * FROM t1
MINUS
SELECT * FROM t2
use this to show the deletes:
SELECT * FROM t2
WHERE NOT EXISTS(SELECT 1 FROM t1 WHERE t1.primary_key = t2.primary_key)
and finally this to check the total number of records are identical
SELECT count(*) FROM t1
SELECT count(*) FROM t2
Note: If there are other sessions updating t1 it could be tricky spotting your updates.

Triggers really should be avoided but ...
If you are in a non-production environment you can set up a trigger to perform logging to a new table. You need 5 fields something like this:
LogTime DateTime;
Table Varchar2(50); -- Table Name
Action Char; -- Insert, Update or Delete
OldRec Blob; -- Concatenate all your field Values
NewRec Blob; -- Ditto
The Beauty of this is that you can select all the OldRecs and NewRecs for a given timespan into text files. A comparison tool will assist by highlighting your changes for you.
Any help ?

I have used Toad for MySQL very successfully in times past (for both the Schema and Data). I see it is also compatible with Oracle.

Try liquibase, it provides the version control mechanism for database.

Related

Copy a table data from one database to another database SQL

I have had a look at similar problems, however none of the answers helped in my case.
Just a little bit of background. I have Two databases, both have the same table with the same fields and structure. Data already exists in both tables. I want to overwrite and add to the data in db1.table from db2.table the primary ID is causing a problem with the update.
When I use the query:
USE db1;
INSERT INTO db2.table(field_id,field1,field2)
SELECT table.field_id,table.field1,table.field2
FROM table;
It works to a blank table, because none of the primary keys exist. As soon as the primary key exists it fails.
Would it be easier for me to overwrite the primary keys? or find the primary key and update the fields related to the field_id? Im really not sure how to go ahead from here. The data needs to be migrated every 5min, so possibly a stored procedure is required?
first you should try to add new records then update all records.you can create a procedure like below code
PROCEDURE sync_Data(a IN NUMBER ) IS
BEGIN
insert into db2.table
select *
from db1.table t
where t.field_id not in (select tt.field_id from db2.table tt);
begin
for t in (select * from db1.table) loop
update db2.table aa
set aa.field1 = t.field1,
aa.field2 = t.field2
where aa.field_id = t.field_id;
end loop;
end;
END sync_Data
Set IsIdentity to No in Identity Specification on the table in which you want to move data, and after executing your script, set it to Yes again
I ended up just removing the data in the new database and sending it again.
DELETE FROM db2.table WHERE db2.table.field_id != 0;
USE db1;
INSERT INTO db2.table(field_id,field1,field2)
SELECT table.field_id,table.field1,table.field2
FROM table;
Its not very efficient, but gets the job done. I couldnt figure out the syntax to correctly do an UPDATE or to change the IsIdentity field within MariaDB, so im not sure if they would work or not.
The overhead of deleting and replacing non-trivial amounts of data for an entire table will be prohibitive. That said I'd prefer to update in place (merge) over delete /replace.
USE db1;
INSERT INTO db2.table(field_id,field1,field2)
SELECT t.field_id,t.field1,t.field2
FROM table t
ON DUPLICATE KEY UPDATE field1 = t.field1, field2 = t.field2
This can be used inside a procedure and called every 5 minutes (not recommended) or you could build a trigger that fires on INSERT and UPDATE to keep the tables in sync.
INSERT INTO database1.tabledata SELECT * FROM database2.tabledata;
But you have to keep length of varchar length larger or equal to database2 and keep the same column name

Using value in deleted record in SQL Server

I need to delete record and search by its Id in anther query as this
select * from Flat
WHERE Flat.nu in (delete top (1) from temp output deleted.nu)
I think you can't run those with each other.
I suggest you to use a (temporary table): tempIds(id int).
Then use output clause like this:
delete top(1) from temp
output deleted.id into tempIds;
Note: It's better to use CTE to delete first row.
Then query over tempIds table and after that clear tempIds.
Try this way.. it may help you out.
DECLARE #ID_CAPTURE TABLE (ID Int)
DELETE TOP(1) FROM TEMP
OUTPUT deleted.Nu into #ID_CAPTURE
SELECT * FROM FLAT WHERE NU IN (SELECT * FROM #ID_CAPTURE)
The above snippet will work for you in case of multiple records too.

how to know how many rows will be affected before running a query in microsoft sql server 2008

i've read a bit about ROWCOUNT but its not exactly what im looking for. from my understanding rowcount states the number of rows affected AFTER you run the query. what im looking for is knowing BEFORE you run the query. is this possible?
You can also use BEGIN TRANSACTION before the operation is executed. You can see the number of rows affected. From there, either COMMIT the results or use ROLLBACK to put the data back in the original state.
BEGIN TRANSACTION;
UPDATE table
SET col = 'something'
WHERE col2 = 'something else';
Review changed data and then:
COMMIT;
or
ROLLBACK;
Short answer is no..
You cannot get the number of rows before executing the query..atleast in SQL server.
The best way to do it is use
Select count(*) from <table> where <condtion>
then execute your actual query
[delete]or [update] [set col='val']
from <table> where <condtion>
The estimated execution plan is going to give you rows affected based on statistics, so it won't really help you in this case.
What I would recommend is copying your UPDATE statement or DELETE statement and turning it into a SELECT. Run that to see how many rows come back and you have your answer to how many rows would have been updated or deleted.
Eg:
UPDATE t
SET t.Value = 'Something'
FROM MyTable t
WHERE t.OtherValue = 'Something Else'
becomes:
SELECT COUNT(*)
FROM MyTable t
WHERE t.OtherValue = 'Something Else'
Simplest solution is to replace the columns in the SELECT * FROM... with SELECT Count(*) FROM ... and the rest of your query(the WHERE clause needs to be the same) before you run it. This will tell you how many rows will be affected
The simplest solution doesn't seem to work in a case where theres a subquery. How would you select count(*) of this update:
BEGIN TRANSACTION;
update Table1 t1 set t1.column = t2.column
from (
SELECT column from Table2 t2
) AA
where t1.[Identity] = t2.[Identity]
COMMIT;
Here I think you need the BEGIN TRANSACTION

How to create a stored procedure which pulls data from multiple tables that are not linked What do i do

I need to create a stored procedure which pulls data from multiple tables that are not linked what do i do .Basically i got a few tables that are not linked and all i need to do is pull all the data from all those tables.
PLEASE HELP MY LIFE DEPENDS ON THIS
Just do several selects?
select * from MyTable1;
select * from MyTable2;
select * from MyTable3;
You can then access each of those tables from your calling code. I'd include an example on how to do that, but you don't include any details about what language you are calling from.. details I would have included if my life depended on it :)
If you mean you have rows in several tables, and you want to pull them all back then you can do that by doing a UNION.
What do you mean by 'not linked'? Are they on the same sql server instance?
If so, just select from the full schema name.
Eg.
Select * from database1.dbo.table
Select * from database2.dbo.table
If you want a single result set you can use the JOIN keyword whether or not the tables have foreign key relationships defined; just specify which columns you would like to join the tables on.
Alternatively, you can use multiple result sets and just have multiple SELECT statements.
Your questions is not clear, but if you are trying to pull just certain things from certain tables and then return them to the user, can do something like this:
CREATE PROCEDURE spMyTestProc
AS
DECLARE #F1 int
DECLARE #F2 int
DECLARE #F3 int
DECLARE #f4 char(10)
SELECT #f1 = FIELD1 from MYTABLE1
SELECT #F2 = FIELD2 FROM MYTABLE2
SELECT #F3 = FIELD3, #F4=FIELD4 FROM MYTABLE3
/* NOW return the result set to the user, it'll come back just like a regular select */
SELECT #F1 AS F1, #F2 AS F2, #F3 AS F3, #F4=F4
The presence or absence of primary or foreign keys doesn't prevent you from joining the tables. (It won't be particularly fast, but you can do it.) Neither does their existing in separate database instances.
You say that your databases aren't linked. From this, I have to infer that the database you're writing the stored procedure in likely has no access to the 2nd database; if that's the case, you won't be able to access it anyway. You need to add a link to the 2nd database using Enterprise Manager.
Once you've done that, you can reference the tables in the 2nd database using its schema name as below:
SELECT *
FROM foo.employees
where foo is the schema name.
Good luck.
SELECT Field1, Field2, Field3 FROM Table1
UNION ALL
SELECT F1, F2, F3 FROM Table2
UNION ALL
SELECT Fld1, Fld2, Fld3 FROM Table3;
This will pull all data from all three tables into single output.
Check that other table fields match type of the first table and you are good to go.

How can I create a copy of an Oracle table without copying the data?

I know the statement:
create table xyz_new as select * from xyz;
Which copies the structure and the data, but what if I just want the structure?
Just use a where clause that won't select any rows:
create table xyz_new as select * from xyz where 1=0;
Limitations
The following things will not be copied to the new table:
sequences
triggers
indexes
some constraints may not be copied
materialized view logs
This also does not handle partitions
I used the method that you accepted a lot, but as someone pointed out it doesn't duplicate constraints (except for NOT NULL, I think).
A more advanced method if you want to duplicate the full structure is:
SET LONG 5000
SELECT dbms_metadata.get_ddl( 'TABLE', 'MY_TABLE_NAME' ) FROM DUAL;
This will give you the full create statement text which you can modify as you wish for creating the new table. You would have to change the names of the table and all constraints of course.
(You could also do this in older versions using EXP/IMP, but it's much easier now.)
Edited to add
If the table you are after is in a different schema:
SELECT dbms_metadata.get_ddl( 'TABLE', 'MY_TABLE_NAME', 'OTHER_SCHEMA_NAME' ) FROM DUAL;
create table xyz_new as select * from xyz where rownum = -1;
To avoid iterate again and again and insert nothing based on the condition where 1=2
Using sql developer select the table and click on the DDL tab
You can use that code to create a new table with no data when you run it in a sql worksheet
sqldeveloper is a free to use app from oracle.
If the table has sequences or triggers the ddl will sometimes generate those for you too. You just have to be careful what order you make them in and know when to turn the triggers on or off.
You can do this
Create table New_table as select * from Old_table where 1=2 ;
but be careful
The table you create does not have any Index, PK and so on like the old_table.
DECLARE
l_ddl VARCHAR2 (32767);
BEGIN
l_ddl := REPLACE (
REPLACE (
DBMS_LOB.SUBSTR (DBMS_METADATA.get_ddl ('TABLE', 'ACTIVITY_LOG', 'OLDSCHEMA'))
, q'["OLDSCHEMA"]'
, q'["NEWSCHEMA"]'
)
, q'["OLDTABLSPACE"]'
, q'["NEWTABLESPACE"]'
);
EXECUTE IMMEDIATE l_ddl;
END;
Simply write a query like:
create table new_table as select * from old_table where 1=2;
where new_table is the name of the new table that you want to create and old_table is the name of the existing table whose structure you want to copy, this will copy only structure.
SELECT * INTO newtable
FROM oldtable
WHERE 1 = 0;
Create a new, empty table using the schema of another. Just add a WHERE clause that causes the query to return no data:
WHERE 1 = 0 or similar false conditions work, but I dislike how they look. Marginally cleaner code for Oracle 12c+ IMHO is
CREATE TABLE bar AS
SELECT *
FROM foo
FETCH FIRST 0 ROWS ONLY;
Same limitations apply: only column definitions and their nullability are copied into a new table.
If one needs to create a table (with an empty structure) just to EXCHANGE PARTITION, it is best to use the "..FOR EXCHANGE.." clause. It's available only from Oracle version 12.2 onwards though.
CREATE TABLE t1_temp FOR EXCHANGE WITH TABLE t1;
This addresses 'ORA-14097' during the 'exchange partition' seamlessly if table structures are not exactly copied by normal CTAS operation. I have seen Oracle missing some of the "DEFAULT" column and "HIDDEN" columns definitions from the original table.
ORA-14097: column type or size mismatch in ALTER TABLE EXCHANGE
PARTITION
See this for further read...
you can also do a
create table abc_new as select * from abc;
then truncate the table abc_new. Hope this will suffice your requirement.
Using pl/sql developer you can right click on the table_name either in the sql workspace or in the object explorer, than click on "view" and than click "view sql" which generates the sql script to create the table along with all the constraints, indexes, partitions etc..
Next you run the script using the new_table_name
copy without table data
create table <target_table> as select * from <source_table> where 1=2;
copy with table data
create table <target_table> as select * from <source_table>;
In other way you can get ddl of table creation from command listed below, and execute the creation.
SELECT DBMS_METADATA.GET_DDL('TYPE','OBJECT_NAME','DATA_BASE_USER') TEXT FROM DUAL
TYPE is TABLE,PROCEDURE etc.
With this command you can get majority of ddl from database objects.
Create table target_table
As
Select *
from source_table
where 1=2;
Source_table is the table u wanna copy the structure of.
create table xyz_new as select * from xyz;
-- This will create table and copy all data.
delete from xyz_new;
-- This will have same table structure but all data copied will be deleted.
If you want to overcome the limitations specified by answer:
How can I create a copy of an Oracle table without copying the data?
The task above can be completed in two simple steps.
STEP 1:
CREATE table new_table_name AS(Select * from old_table_name);
The query above creates a duplicate of a table (with contents as well).
To get the structure, delete the contents of the table using.
STEP 2:
DELETE * FROM new_table_name.
Hope this solves your problem. And thanks to the earlier posts. Gave me a lot of insight.