Add primary key to PostgreSQL table only if it does not exist - sql

I have simple table creating script in Postgres 9.1. I need it to create the table with
2-attributes PK only if it does not exist.
CREATE TABLE IF NOT EXISTS "mail_app_recipients"
(
"id_draft" Integer NOT NULL,
"id_person" Integer NOT NULL
) WITH (OIDS=FALSE); -- this is OK
ALTER TABLE "mail_app_recipients" ADD PRIMARY KEY IF NOT EXISTS ("id_draft","id_person");
-- this is problem since "IF NOT EXISTS" is not allowed.
Any solution how to solve this problem? Thanks in advance.

You could do something like the following, however it is better to include it in the create table as a_horse_with_no_name suggests.
if NOT exists (select constraint_name from information_schema.table_constraints where table_name = 'table_name' and constraint_type = 'PRIMARY KEY') then
ALTER TABLE table_name
ADD PRIMARY KEY (id);
end if;

Why not include the PK definition inside the CREATE TABLE:
CREATE TABLE IF NOT EXISTS mail_app_recipients
(
id_draft Integer NOT NULL,
id_person Integer NOT NULL,
constraint pk_mail_app_recipients primary key (id_draft, id_person)
)

You can try to DROP it before creating it (DROP has the IF EXISTS clause):
ALTER TABLE mail_app_recipients DROP CONSTRAINT IF EXISTS mail_app_recipients_pkey;
ALTER TABLE mail_app_recipients ADD CONSTRAINT mail_app_recipients_pkey PRIMARY KEY ("id_draft","id_person");
Note that this require that you give a name to the primary key constraint - in this example mail_app_recipients_pkey.

Related

How to redefine the constraint in a field?

the table was built as follow
create table schema1.detail(
ornum char(6) foreign key references schema1.menu(ornum),
num int,
pdname char(20),
price money check(price>0) default null,
amount int check(amount>0) not null,
primary key (ornum,num)
)
and I want to redefine the field 'amount' as amount>0 and amount<=1000 not null
but I don't know how to do it.
Well, if you already had data in your table you would have needed to keep it so you would have needed to first find out the name of the constraint (since your create script does not provide names to the constraints, SQL Server does it automatically for you), then drop the constraint and create a new one.
To do that, you would need to do something like this to find out the name of the constraints in your table:
SELECT TABLE_NAME,
COLUMN_NAME,
CHECK_CLAUSE,
cc.CONSTRAINT_SCHEMA,
cc.CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS cc
INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE c
ON cc.CONSTRAINT_NAME = c.CONSTRAINT_NAME
WHERE TABLE_NAME = 'detail'
AND cc.CONSTRAINT_SCHEMA = 'schema1'
ORDER BY CONSTRAINT_SCHEMA,
TABLE_NAME,
COLUMN_NAME
Then you need to drop the constraint and recreate it:
ALTER TABLE dbo.detail
DROP CONSTRAINT <constraint name> -- you got from the query above
ALTER TABLE detail
ADD CONSTRAINT CK_detail_amount CHECK(amount>0 AND amount<1000)
However, since this is a brand new table, I would suggest drop the table all together and re-create it, this time with proper names for the constraints:
drop table schema1.detail;
create table schema1.detail (
ornum char(6),
num int,
pdname char(20),
price money null, -- there is no need for the default keyword here...
amount int check(amount>0) not null,
constraint PK_detail primary key (ornum,num),
constraint FK_detail_menu foreign key (ornum) references schema1.menu(ornum),
constraint CK_detail_price check(price>0),
constraint CK_detail_amount check(amount>0 and amount <1000)
);
It's best practice to give your constraints meaningful names.
UPDATED
alter table schema1.detail drop constraint [yourConstraintName] ;
alter table schema1.detail add constraint [yourConstraintName] check (amount>0 and amount < 1000)
check constraint like "fieldname BETWEEN 0 and 1000"
or
amount int check (amount>0 AND amount <1000) not null,

How to ADD a CONSTRAINT NAME to an already EXISTING CONSTRAINT

Is there a way to give names to already existing constraints?
for example :
create table employee (emp_id number(10),emp_name varchar2(20),
dept_id number(10),foreign key(dept_id) references department(dept_id));
In the above query I haven't named the foreign key constraint so after the creation of the table can I give a name to it also can the foreign key constraint be dropped without dropping the column??
Yes you can rename a constraint like this:
alter table t rename constraint old_name to new_name
Edit: I've forgotten about the second question. Yes you can drop a constraint without dropping the column. If you do not know the name of the constraint you can find it in user_constraints table like this:
select constraint_name
from user_constraints
where table_name = 'your_table'
and constraint_type ='R'
For the second part, yes you can drop the foreign key constraint.

General error: 1 OCIStmtExecute: ORA-00001: unique constraint (HR.SYS_C004023) violated?

I can identify the error message that its due to unique value constraint, my table is 'branches',and where did SYS_C004023 come. I have checked the branches table and there is no value duplication. What could be the issue.
where did SYS_C004023 come
This is a system-generated constraint name, which Oracle creates when a constraint is created without being explicitly named e.g.
create table mytable (col1 integer primary key);
The primary key constraint on mytable will be system-generated since I didn't explicitly name it like this:
create table mytable (col1 integer constraint mytable_pk primary key);
You can find out what table this constraint is on like this:
select table_name
from all_constraints
where owner = 'HR'
and constraint_name = 'SYS_C004023';
And you can find out which columns it makes unique like this:
select column_name
from all_cons_columns
where owner = 'HR'
and constraint_name = 'SYS_C004023';
there is no value duplication
No, there won't be, thanks to the constraint. What there has been is a failed attempt to insert or update a row so that the uniqueness constraint is violatedd.

How do I ALTER a PostgreSQL table and make a column unique?

I have a table in PostgreSQL where the schema looks like this:
CREATE TABLE "foo_table" (
"id" serial NOT NULL PRIMARY KEY,
"permalink" varchar(200) NOT NULL,
"text" varchar(512) NOT NULL,
"timestamp" timestamp with time zone NOT NULL
)
Now I want to make the permalink unique across the table by ALTER-ing the table.
I figured it out from the PostgreSQL docs, the exact syntax is:
ALTER TABLE the_table ADD CONSTRAINT constraint_name UNIQUE (thecolumn);
Thanks Fred.
Or, have the DB automatically assign a constraint name using:
ALTER TABLE foo ADD UNIQUE (thecolumn);
it's also possible to create a unique constraint of more than 1 column:
ALTER TABLE the_table
ADD CONSTRAINT constraint_name UNIQUE (column1, column2);
Try the following
ALTER TABLE table_name ADD UNIQUE (column_name);

How do I create a foreign key in SQL Server?

I have never "hand-coded" object creation code for SQL Server and foreign key decleration is seemingly different between SQL Server and Postgres. Here is my sql so far:
drop table exams;
drop table question_bank;
drop table anwser_bank;
create table exams
(
exam_id uniqueidentifier primary key,
exam_name varchar(50),
);
create table question_bank
(
question_id uniqueidentifier primary key,
question_exam_id uniqueidentifier not null,
question_text varchar(1024) not null,
question_point_value decimal,
constraint question_exam_id foreign key references exams(exam_id)
);
create table anwser_bank
(
anwser_id uniqueidentifier primary key,
anwser_question_id uniqueidentifier,
anwser_text varchar(1024),
anwser_is_correct bit
);
When I run the query I get this error:
Msg 8139, Level 16, State 0, Line 9
Number of referencing columns in
foreign key differs from number of
referenced columns, table
'question_bank'.
Can you spot the error?
And if you just want to create the constraint on its own, you can use ALTER TABLE
alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn ) references MyOtherTable(PKColumn)
I wouldn't recommend the syntax mentioned by Sara Chipps for inline creation, just because I would rather name my own constraints.
create table question_bank
(
question_id uniqueidentifier primary key,
question_exam_id uniqueidentifier not null,
question_text varchar(1024) not null,
question_point_value decimal,
constraint fk_questionbank_exams foreign key (question_exam_id) references exams (exam_id)
);
You can also name your foreign key constraint by using:
CONSTRAINT your_name_here FOREIGN KEY (question_exam_id) REFERENCES EXAMS (exam_id)
I like AlexCuse's answer, but something you should pay attention to whenever you add a foreign key constraint is how you want updates to the referenced column in a row of the referenced table to be treated, and especially how you want deletes of rows in the referenced table to be treated.
If a constraint is created like this:
alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn )
references MyOtherTable(PKColumn)
.. then updates or deletes in the referenced table will blow up with an error if there is a corresponding row in the referencing table.
That might be the behaviour you want, but in my experience, it much more commonly isn't.
If you instead create it like this:
alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn )
references MyOtherTable(PKColumn)
on update cascade
on delete cascade
..then updates and deletes in the parent table will result in updates and deletes of the corresponding rows in the referencing table.
(I'm not suggesting that the default should be changed, the default errs on the side of caution, which is good. I'm just saying it's something that a person who is creating constaints should always pay attention to.)
This can be done, by the way, when creating a table, like this:
create table ProductCategories (
Id int identity primary key,
ProductId int references Products(Id)
on update cascade on delete cascade
CategoryId int references Categories(Id)
on update cascade on delete cascade
)
create table question_bank
(
question_id uniqueidentifier primary key,
question_exam_id uniqueidentifier not null constraint fk_exam_id foreign key references exams(exam_id),
question_text varchar(1024) not null,
question_point_value decimal
);
--That will work too. Pehaps a bit more intuitive construct?
To Create a foreign key on any table
ALTER TABLE [SCHEMA].[TABLENAME] ADD FOREIGN KEY (COLUMNNAME) REFERENCES [TABLENAME](COLUMNNAME)
EXAMPLE
ALTER TABLE [dbo].[UserMaster] ADD FOREIGN KEY (City_Id) REFERENCES [dbo].[CityMaster](City_Id)
If you want to create two table's columns into a relationship by using a query try the following:
Alter table Foreign_Key_Table_name add constraint
Foreign_Key_Table_name_Columnname_FK
Foreign Key (Column_name) references
Another_Table_name(Another_Table_Column_name)
Like you, I don't usually create foreign keys by hand, but if for some reason I need the script to do so I usually create it using ms sql server management studio and before saving then changes, I select Table Designer | Generate Change Script
This script is about creating tables with foreign key and I added referential integrity constraint sql-server.
create table exams
(
exam_id int primary key,
exam_name varchar(50),
);
create table question_bank
(
question_id int primary key,
question_exam_id int not null,
question_text varchar(1024) not null,
question_point_value decimal,
constraint question_exam_id_fk
foreign key references exams(exam_id)
ON DELETE CASCADE
);
Necromancing.
Actually, doing this correctly is a little bit trickier.
You first need to check if the primary-key exists for the column you want to set your foreign key to reference to.
In this example, a foreign key on table T_ZO_SYS_Language_Forms is created, referencing dbo.T_SYS_Language_Forms.LANG_UID
-- First, chech if the table exists...
IF 0 < (
SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'T_SYS_Language_Forms'
)
BEGIN
-- Check for NULL values in the primary-key column
IF 0 = (SELECT COUNT(*) FROM T_SYS_Language_Forms WHERE LANG_UID IS NULL)
BEGIN
ALTER TABLE T_SYS_Language_Forms ALTER COLUMN LANG_UID uniqueidentifier NOT NULL
-- No, don't drop, FK references might already exist...
-- Drop PK if exists
-- ALTER TABLE T_SYS_Language_Forms DROP CONSTRAINT pk_constraint_name
--DECLARE #pkDropCommand nvarchar(1000)
--SET #pkDropCommand = N'ALTER TABLE T_SYS_Language_Forms DROP CONSTRAINT ' + QUOTENAME((SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
--WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
--AND TABLE_SCHEMA = 'dbo'
--AND TABLE_NAME = 'T_SYS_Language_Forms'
----AND CONSTRAINT_NAME = 'PK_T_SYS_Language_Forms'
--))
---- PRINT #pkDropCommand
--EXECUTE(#pkDropCommand)
-- Instead do
-- EXEC sp_rename 'dbo.T_SYS_Language_Forms.PK_T_SYS_Language_Forms1234565', 'PK_T_SYS_Language_Forms';
-- Check if they keys are unique (it is very possible they might not be)
IF 1 >= (SELECT TOP 1 COUNT(*) AS cnt FROM T_SYS_Language_Forms GROUP BY LANG_UID ORDER BY cnt DESC)
BEGIN
-- If no Primary key for this table
IF 0 =
(
SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
AND TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'T_SYS_Language_Forms'
-- AND CONSTRAINT_NAME = 'PK_T_SYS_Language_Forms'
)
ALTER TABLE T_SYS_Language_Forms ADD CONSTRAINT PK_T_SYS_Language_Forms PRIMARY KEY CLUSTERED (LANG_UID ASC)
;
-- Adding foreign key
IF 0 = (SELECT COUNT(*) FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_T_ZO_SYS_Language_Forms_T_SYS_Language_Forms')
ALTER TABLE T_ZO_SYS_Language_Forms WITH NOCHECK ADD CONSTRAINT FK_T_ZO_SYS_Language_Forms_T_SYS_Language_Forms FOREIGN KEY(ZOLANG_LANG_UID) REFERENCES T_SYS_Language_Forms(LANG_UID);
END -- End uniqueness check
ELSE
PRINT 'FSCK, this column has duplicate keys, and can thus not be changed to primary key...'
END -- End NULL check
ELSE
PRINT 'FSCK, need to figure out how to update NULL value(s)...'
END
I always use this syntax to create the foreign key constraint between 2 tables
Alter Table ForeignKeyTable
Add constraint `ForeignKeyTable_ForeignKeyColumn_FK`
`Foreign key (ForeignKeyColumn)` references `PrimaryKeyTable (PrimaryKeyColumn)`
i.e.
Alter Table tblEmployee
Add constraint tblEmployee_DepartmentID_FK
foreign key (DepartmentID) references tblDepartment (ID)