I have some columns with no primary key and want to add a primary key column.
NAME Age
-------------
Peter 45
Bob 25
John 56
Peter 45
Some collegues suggest to add a PK with a sequences and triggers:
Add a auto increment primary key to existing table in oracle
This is nice, but my customers use a Database User with no rights to add sequences or triggers.
I want to prevent to contact dozens of DBA administrators to alter user rights or to run my scripts.
This is my suggestion to add a PK with only an update statement: (I need help in Step 2)
Step 1: Create the ID column (I have DB rights for this)
ALTER TABLE PERSON ADD ID NUMBER(10,0);
Step 2: Question: Can I initialize the ID column with unique values based on the order of the rows or something else? How?
UPDATE PERSON SET ID = something-unique
Step 3: Add the primary key contraint afterwords: (I DB have rights for this)
ALTER TABLE PERSON ADD CONSTRAINT PK_ID PRIMARY KEY(ID);
Step 4: Afterwords: the primary key is managed and added by my application.
This will be the result:
ID(PK) NAME Age
---------------------
1 Peter 45
2 Bob 25
3 John 56
4 Peter 45
Thanks folks!
Update person set id = rownum;
THis idea is very childish, but should work fine if your table doesnot have large amount of rows.
For step 2, run a for loop like:
declare
i pls_integer :=1;
begin
for rec in (select name,age, rowid from table_name)
loop
update table_name set id = i
where
table_name.name=rec.name
and table_name.age=rec.age
and table_name.rowid = rec.rowid;
i:=i+1;
end loop;
end;
Related
This question already has answers here:
Oracle SQL - Add Primary Key to table
(2 answers)
Closed 5 years ago.
this is my table.In this table i want to add a primary key column name "emp_id" as the first column .I don't know how to do it .So,can you please help me!
EMP_NAME EMP_POS SALARY GENDER
----------------- ----------------- -------------- ------
anand worker 10000 M
balu manager 50000 M
carl manager 50000 M
riya md 60000 F
prabhu owner 99999999 M
The old way of doing this is a multi-step process:
add the column which will be the primary key
update the column
enforce the primary key.
Something like this:
create sequence t23_id;
alter table t23 add id number;
update t23
set id = t23_id.nextval
;
alter table t23 add constraint t23_pk primary key (id);
In 12c Oracle added Identity columns (like SQL Server auto-incrementing columns). This reduces the number of steps to two:
alter table t23i add id number GENERATED ALWAYS AS IDENTITY primary key;
alter table t23i add constraint t23i_pk primary key (id);
Unfortunately it can't be done in one step. This ...
alter table t23i add id number GENERATED ALWAYS AS IDENTITY primary key;
...hurls ...
ORA-01758: table must be empty to add mandatory (NOT NULL) column
Livesql demo
Introduce identity column:
see http://sql-plsql.blogspot.sg/2014/11/add-identity-column-to-table.html
Reorder the columns:
see http://www.dba-oracle.com/t_change_column_order_within_oracle_table.htm
Hope these references help.
I Have table three tables:
The first one is emps:
create table emps (id number primary key , name nvarchar2(20));
The second one is cars:
create table cars (id number primary key , car_name varchar2(20));
The third one is accounts:
create table accounts (acc_id number primary key, woner_table nvarchar2(20) ,
woner_id number references emps(id) references cars(id));
Now I Have these values for selected tables:
Emps:
ID Name
-------------------
1 Ali
2 Ahmed
Cars:
ID Name
------------------------
107 Camery 2016
108 Ford 2012
I Want to
Insert values in accounts table so its data should be like this:
Accounts:
Acc_no Woner_Table Woner_ID
------------------------------------------
11013 EMPS 1
12010 CARS 107
I tried to perform this SQL statement:
Insert into accounts (acc_id , woner_table , woner_id) values (11013,'EMPS',1);
BUT I get this error:
ERROR at line 1:
ORA-02291: integrity constraint (HR.SYS_C0016548) violated - parent key not found.
This error occurs because the value of woner_id column doesn't exist in cars table.
My work require link tables in this way.
How Can I Solve This Problem Please ?!..
Mean: How can I reference tables in previous way and Insert values without this problem ?..
One-of relationships are tricky in SQL. With your data structure here is one possibility:
create table accounts (
acc_id number primary key,
emp_id number references emps(id),
car_id number references car(id),
id as (coalesce(emp_id, car_id)),
woner_table as (case when emp_id is not null then 'Emps'
when car_id is not null then 'Cars'
end),
constraint chk_accounts_car_emp check (emp_id is null or car_id is null)
);
You can fetch the id in a select. However, for the insert, you need to be explicit:
Insert into accounts (acc_id , emp_id)
values (11013, 1);
Note: Earlier versions of Oracle do not support virtual columns, but you can do almost the same thing using a view.
Your approach should be changed such that your Account table contains two foreign key fields - one for each foreign table. Like this:
create table accounts (acc_id number primary key,
empsId number references emps(id),
carsId number references cars(id));
The easiest, most straightforward method to do this is as STLDeveloper says, add additional FK columns, one for each table. This also bring along with it the benefit of the database being able to enforce Referential Integrity.
BUT, if you choose not to do, then the next option is to use one FK column for the the FK values and a second column to indicate what table the value refers to. This keeps the number of columns small = 2 max, regardless of number of tables with FKs. But, this significantly increases the programming burden for the application logic and/or PL/SQL, SQL. And, of course, you completely lose Database enforcement of RI.
I am trying to explain what this table does, but unable to see what is happening here. Any suggestion?
CREATE TABLE EMP
(
ID INT NOT NULL PRIMARY KEY,
MGID INT REFERENCES EMP (ID),
NAME VARCHAR(30) NOT NULL
);
It's creating a table called EMP which describes employees. Each employee is identified by a surrogate ID number, has a NAME attribute, and a relationship with a manager identified by MGID.
This code creates a table that's called EMP, with a primary key column called ID of type int, a foreigen key referencing that column called MGID, and a string column called NAME.
Using a foriegn key to the same table enables you to create parent/child relationship for rows in that table.
For instance, if you have an employee that's called Raza, and his manager is calld Far, You will have a row for the manager and a row for Raza and the value of MGID in that row would point to the ID of Far
Assuming that you have some basic knowledge of DBMS, I think you stuck with 'REFERENCES' keyword.
It creates a Parent/Child relationship between ID and MGID.
As you know, the table is for Employee(as the name suggested 'Emp'), Manager is also an employee.
So,before referencing to any employee as a manager it must have entry in table as employee. To perform this kind of validations, 'REFERENCES' keyword can be used.
For example,
ID MGID NAME
1 null a
2 1 b
3 1 c
Above data is valid but,
ID MGID NAME
1 null a
2 3 b
3 1 c
Above data will violate the referential integrity constraints as any employee with ID 3 is not existed yet.
Hope it helps.
I am trying to make a constraint that will keep ids unique for specific users.
Each user is a separate entity within the world so 2 people having 1 as id is not a problem. I just don't want one person to have the same id twice.
For example:
This would be acceptable:
User Id
John 1
John 2
Alice 1
Alice 2
This would not be ok:
User Id
John 1
John 1 -- problem
Alice 1
Alice 2
Just add a Unique constraint over both columns to your CREATE TABLE statement:
CREATE TABLE person(
... -- more columns
username text
,person_id int
,UNIQUE (username, person_id)
);
That does it. I see that #Hamlet and #Frank already commented likewise.
Creating a unique index on these two columns would also work. This is usually what happens under the covers to enforce the constraint.
I have a table which has these columns:
Id (Primary Key): the id.
OwnerId (Foreign Key): the id of the owner, which resides in another table.
TypeId (Foreign Key): the type of thing this record represents. There are a finite number of types, which are represented in another table. This links to that table.
TypeCreatorId (ForeignKey): the owner of the type represented by TypeId.
SourceId (Foreign Key): this isn't important to this question.
I need to constrain this table such that for each Id, there can be only one of each TypeCreatorId. I hope that makes sense!
For SQL Server, you have two options:
create a UNIQUE CONSTRAINT
ALTER TABLE dbo.YourTable
ADD CONSTRAINT UNIQ_Id_TypeCreator UNIQUE(Id, TypeCreatorId)
create a UNIQUE INDEX:
CREATE UNIQUE INDEX UIX_YourTable_ID_TypeCreator
ON dbo.YourTable(Id, TypeCreatorId)
Basically, both things achieve the same thing - you cannot have two rows with the same (Id, TypeCreatorId) values.
Simply create a unique index on OwnerId and TypeCreatorId.
An example using MySQL (sorry, I don't use SQL Server):
alter table yourTable
add unique index idx_newIndex(OwnerId, TypeCreatorId);
Example. I'll just put here what would happen with this new unique index:
OwnerId | TypeCreatorId
--------+--------------
1 | 1
1 | 2 -- This is Ok
2 | 1 -- Ok too
2 | 2 -- Ok again
1 | 2 -- THIS WON'T BE ALLOWED because it would be a duplicate