How can I make a copy of a table with a PK? - sql

In an Oracle 10g database, I would like to make a copy of an existing table. I would like it to have the same data and rows as the original table. The original table uses a PK though, so I'm not sure how to copy it and keep them unique.

oracle maintains the pk as a column constraint. you have to copy the table and subsequently create this constraint for the new table.
the following code illustrates how to get your job done.
-- setting up table t1 - this is just for the sake of demonstration
create table t1 (
t_id integer
, t_data varchar2(40)
);
alter table t1 modify ( t_id constraint t1_pk primary key );
insert into t1 values ( 1, 'test');
insert into t1 values ( 2, 'another test');
insert into t1 values ( 3, 'final test');
commit;
-- copying table t1 (definition + contents) and defining the pk
create table t2 as ( select * from t1 );
alter table t2 modify ( t_id constraint t2_pk primary key );
hope this helps,
best regards,
carsten

You can make the copy using
CREATE TABLE dummy_copy as SELECT * FROM dummy//Structure and data
Also you could use dbms_metadata.get_ddl to get the associated constraints of the table
and create it with all the checks
SELECT dbms_metadata.get_ddl( 'TABLE', 'dummy' ) FROM DUAL;

Or you can just do it all in one statement:
create table mike_temp_1 (
col1,
col2,
col3,
col4,
col5,
constraint xpk_mike_temp_1 primary key (col1)
)
as select *
from OLD_POLICY_TERM;
I think the format of specifying column names when using create table as select is a bit fiddly in that I don't believe that you can specify data types (sort of obvious really) but you can specify constraints such as not null, primary key and foreign key.

Related

How to remove/Delete the effect of UNIQUE KEY from TABLE

I have UNIQUE KEY attribute on my Table. For my project I deleted that UNIQUE KEY from table , but when try to enter data it still giving the error of UNIQUE KEY VIOLATION.
Already done
to check to commit the database .
to refreshed the entire database.
to find that CONSTRAINT on schema.
SELECT DISTINCT table_name
FROM all_indexes
WHERE index_name = 'CONSTRAINT_NAME';
The above query returns no data (Constraint not found).
I want my data duplicate for one employee without UNIQUE KEY VIOLATION ERROR
Below are some of the queries you can run and check if there is specified index, constraints exist on the table and once you find you can simply drop it. Maybe your unique index was created before the constraint was created:
SELECT * FROM user_cons_columns WHERE table_name = '<your table name>';
select column_name from user_ind_columns where index_name = '<index_name>';
select column_name from user_cons_columns where constraint_name = '<index_name>';
Use below command for dropping index:
DROP INDEX index_name;
Use below command for dropping constraints:
ALTER TABLE <table_name>
DROP CONSTRAINT <constraint_name>
[TL;DR] If you have a UNIQUE INDEX without a UNIQUE CONSTRAINT then you will get the same error message. You need to make sure you have dropped both the index and the constraint.
CREATE TABLE test_data ( id NUMBER );
CREATE UNIQUE INDEX test_data__id__u ON test_data ( id );
ALTER TABLE test_data ADD CONSTRAINT test_data__id__u UNIQUE ( id );
INSERT INTO test_data ( id ) VALUES ( 1 );
INSERT INTO test_data ( id ) VALUES ( 1 );
Will insert one row and will give ORA-00001: unique constraint (FIDDLE_ALGCPMTPWFJZCXIPXNLR.TEST_DATA__ID__U) violated for the second.
If you do:
SELECT * FROM user_constraints WHERE table_name = 'TEST_DATA';
SELECT * FROM user_indexes WHERE table_name = 'TEST_DATA';
Then it will show there is an index and a constraint on the table.
Then if you drop the constraint:
ALTER TABLE test_data DROP CONSTRAINT test_data__id__u;
and try to do:
INSERT INTO test_data ( id ) VALUES ( 1 );
Then you will get:
ORA-00001: unique constraint (FIDDLE_ALGCPMTPWFJZCXIPXNLR.TEST_DATA__ID__U) violated
If you look at the indexes and constraints again:
SELECT * FROM user_constraints WHERE table_name = 'TEST_DATA';
SELECT * FROM user_indexes WHERE table_name = 'TEST_DATA';
Then it will show no constraints but the index is still there. You need to make sure the unique index has been dropped too.
DROP INDEX test_data__id__u;
INSERT INTO test_data ( id ) VALUES ( 1 );
Will then insert the row.
db<>fiddle here

How to insert a query into SQLite with an autoincrementing value for each row

Suppose I am inserting the following queryset into a new table in SQLite:
CREATE TABLE queryset_cache AS
SELECT ROW_NUMBER() over () AS rowid, * FROM mytable ORDER BY product;
Is it possible to either:
Set the rowid as auto-incrementing PK in sqlite from the insert, or;
Exclude the rowid and have SQLite auto-add in an autoincrementing primary key for each inserted record.
How would this be done?
Currently, without that when I do the insert, the rowid is not indexed.
rowid is already there. You can just do:
CREATE TABLE queryset_cache AS
SELECT t.*
FROM mytable t
ORDER BY product;
You will see it if you do:
SELECT rowid, t.*
FROM queryset_cache;
Here is a db<>fiddle
Auo increment should solve this. Documentation here:
https://www.sqlite.org/autoinc.html
Create source table:
create table sourceTable (oldID integer, data TEXT);
Add source data:
insert into sourceTable values(7, "x");
insert into sourceTable values(8, "y");
insert into sourceTable values(9, "z");
Create target table with auto-increment:
create table target(newID INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT);
Move data from source to target:
insert into target select null, data from sourceTable
If we have a table like:
create table employee (empID integer, name text , address text);
insert data into this table.
create a table in which you want to insert employee table data:
create table newEmployee (newempID integer PRIMARY KEY, name text , address text);
copy data to newEmployee table:
insert into newEmployee select * from employee
(select * from employee) to copy all the columns

MERGE Constraint Error on self referenced table

MERGE is raising an Error
ORA-02291: integrity constraint violated-parent key not found
on inserting into a self referenced table.
If I change query a little bit with no matter, it will work.
Am I do something wrong.
Execution order:
Preparement stuff
First MERGE query (will not work)
Second MERGE query (will work)
The order of the columns in the MERGE query does not matter. You also can run the second MERGE before first.
If you would like to restart your test, start at DROP TABLE TGR.
First some preparement:
DROP TABLE SRC;
CREATE TABLE SRC (
ID VARCHAR(20) PRIMARY KEY,
PARENT VARCHAR(20)
);
INSERT INTO SRC SELECT '1', null FROM DUAL;
INSERT INTO SRC SELECT '2', '1' FROM DUAL;
DROP TABLE TRG;
CREATE TABLE TRG (
ID VARCHAR(20) PRIMARY KEY,
PARENT VARCHAR(20),
CONSTRAINT FK2 FOREIGN KEY(PARENT) REFERENCES TRG(ID)
);
This will not work:
MERGE INTO TRG t USING(
SELECT PARENT, ID FROM SRC
) s ON (t.ID=s.ID)
WHEN NOT MATCHED THEN INSERT(ID,PARENT) VALUES (s.ID,s.PARENT);
But this will work.
MERGE INTO TRG t USING(
SELECT ID, PARENT FROM SRC
) s ON (t.ID=s.ID)
WHEN NOT MATCHED THEN INSERT(ID,PARENT) VALUES (s.ID,s.PARENT);
If you change the datatype of these columns to NUMBER, it will work.
DROP TABLE SRC;
CREATE TABLE SRC (
ID NUMBER PRIMARY KEY,
PARENT NUMBER
);
INSERT INTO SRC SELECT 1, null FROM DUAL;
INSERT INTO SRC SELECT 2, 1 FROM DUAL;
DROP TABLE TRG;
CREATE TABLE TRG (
ID NUMBER PRIMARY KEY,
PARENT NUMBER,
CONSTRAINT FK2 FOREIGN KEY(PARENT) REFERENCES TRG(ID)
);
MERGE INTO TRG t USING(
SELECT PARENT, ID FROM SRC
) s ON (t.ID=s.ID)
WHEN NOT MATCHED THEN INSERT(ID,PARENT) VALUES (s.ID,s.PARENT);
Edit:
Forgot to tell: I am using 12c

SQL check constraint on multiple tables

So If the "Type" is 0, i should be able to add my person in Table B, else not, but the "Type" column is not and shouldn't be in Table B.
You can do this with a foreign key constraint and some trickery.
First, set up a unique constraint on TableA for both type and person:
alter table TableA add constraint unq_TableA_type_person on TableA(type, person);
This allows you set to set up a foreign key constraint. However, you need a type column. For that, you can use a computed column:
alter table TableB add type_for_a as (0); -- it is always 0
Now, just use a foreign key constraint:
alter table TableB add constraint fk_tableA_type_person
foreign key (type_for_a, person) references tableA(type, person);
Voila! You have the constraint in place without having to write any code.
CREATE TABLE T1 (TypeID INT NOT NULL, people VARCHAR(50));
GO
CREATE TABLE T2 ( people VARCHAR(50));
GO
-- creating trigger to insert on the behalf when there is a particular type
CREATE TRIGGER dbo.AfterInsertTrigger
ON T1
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
declare #id int,
#someval char(1)
insert into dbo.T2
select i.people FROM Inserted i
where i.TypeID=0 -- checks only when the id is 0
END
GO
-- inserting people with different id s into Table1
INSERT T1 (TypeID, people) SELECT 1, 'A';
INSERT T1 (TypeID, people) SELECT 0, 'B';
GO
--selecting from tables see what got affected.
select * from T1
select *from T2
--Clean up
DROP TABLE T2;
DROP TABLE T1;
GO

Oracle - updating a sorted table

I found an old table without a primary key, and in order to add one, I have to add a new column and fill it with sequence values. I have another column which contains the time of when the record was created, so I want to insert the sequence values to the table sorted by the column with the time.
I'm not sure how to do it. I tried using PL\SQL - I created a cursor for a query that returns the table with an ORDER BY, and then update for each record the cursor returns but it didn't work.
Is there a smart working way to do this?
Thanks in advance.
Another option is just to use a correlated subquery, with the wrinkle of a nested subquery to generate the row number. Setting up some sample data:
create table t42 (datefield date);
insert into t42 (datefield) values (sysdate - 7);
insert into t42 (datefield) values (sysdate + 6);
insert into t42 (datefield) values (sysdate - 5);
insert into t42 (datefield) values (sysdate + 4);
insert into t42 (datefield) values (sysdate - 3);
insert into t42 (datefield) values (sysdate + 2);
select * from t42;
DATEFIELD
---------
12-JUL-12
25-JUL-12
14-JUL-12
23-JUL-12
16-JUL-12
21-JUL-12
Then adding and populating the new column:
alter table t42 add (id number);
update t42 t1 set t1.id = (
select rn from (
select rowid, row_number() over (order by datefield) as rn
from t42
) t2
where t2.rowid = t1.rowid
);
select * from t42 order by id;
DATEFIELD ID
--------- ----------
12-JUL-12 1
14-JUL-12 2
16-JUL-12 3
21-JUL-12 4
23-JUL-12 5
25-JUL-12 6
Since this is a synthetic key, making it match the order of another column seems a bit pointless, but I guess doesn't do any harm.
To complete the task:
alter table t42 modify id not null;
alter table t42 add constraint t42_pk primary key (id);
First of all, create new field and allow null values.
Then, update field from other table or query. Best approach is to use merge statement.
Here a sample from documentation:
MERGE INTO bonuses D
USING (SELECT employee_id, salary, department_id FROM employees
WHERE department_id = 80) S
ON (D.employee_id = S.employee_id)
WHEN MATCHED THEN UPDATE SET D.bonus = D.bonus + S.salary*.01
DELETE WHERE (S.salary > 8000)
WHEN NOT MATCHED THEN INSERT (D.employee_id, D.bonus)
VALUES (S.employee_id, S.salary*.01)
WHERE (S.salary <= 8000);
Finally, set as non null this new field and promote it to primary key.
Here sample sentences:
ALTER TABLE
customer
MODIFY
(
your_new_field varchar2(100) not null
)
;
ALTER TABLE
customer
ADD CONSTRAINT customer_pk PRIMARY KEY (your_new_field)
;
One simple way is to create a new table, with new column an all other columns:
create table newt (
newtID int primary key not null,
. . .
)
Then insert all the old data into it:
insert into newt
select row_number() over (order by <CreatedAt>), t.*
from t
(You can substitute all the columns in, instead of using "*". Having the columns by name is the better practice. This is shorter, plus, I don't know the column names.)
If you alter the table to add the column, then the column will appear at the end. I find that quite awkward for the primary key. If you do that, though, you can update it as:
with t as (select row_number() over (order by <CreatedAt>) as seqnum, t.*
from t
)
update t
set newtID = seqnum