SQLite option for ADD CONSTRAINT with ON CONFLICT REPLACE - sql

SQLite doesn't support Add Constaints. I have the below SQL. How could I get that supported?
ALTER TABLE mytable ADD CONSTRAINT unique_hash UNIQUE (hash) ON CONFLICT REPLACE
Note: CREATE UNIQUE INDEX won't solve this problem of having ON CONFLICT REPLACE

Related

How to add check constraint on a column in table?

ALTER TABLE Student ADD CONSTRAINT CHK_Student_ID_LENGTH CHECK (LEN([ID]) between 12 and 14);
SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_NAME = 'CHK_Student_ID_LENGTH';
alter table Student drop constraint CHK_Student_ID_LENGTH;
I tried to add check constraint using the first statement. It gave me the below error.
[23000][547] The ALTER TABLE statement conflicted with the CHECK constraint "CHK_Student_ID_LENGTH". The conflict occurred in database, table "Student", column 'ID'.
I tried to check if there was any existing constraint with the same name. But I did not get any. Still I tried to drop the constraint. But then it gave the error:
CHK_Student_ID_LENGTH is not a constraint.
But still add constraint statement gives error saying it already exists. Where am I going wrong?
The error message is a little badly worded, but isn't saying what you think it's saying.
It's not saying that there's already a constraint with the same name. It's saying that the constraint is being violated. That means that there is data already in the table that doesn't meet the requirements of the new constraint you're trying to introduce.
You could use the NOCHECK option to create the constraint whilst allowing existing data to violate it. But this is frequently the wrong thing to do. It is usually more sensible to fix the existing data.
Specifying NOCHECK means that the constraint can't be used by the optimizer to eliminate redundant actions that the logic of the constraint would preclude.
You probably have some records in Your table that conflict with that new constraint.
Just find them and UPDATE/DELETE before adding a contraint.
SELECT *
FROM Student
WHERE LEN([ID]) between 12 and 14
Or try to add that constraint without checking existing values using WITH NOCHECK
ALTER TABLE Student WITH NOCHECK
ADD CONSTRAINT CHK_Student_ID_LENGTH CHECK (LEN([ID]) between 12 and 14);
Tip: In migration files I usually add this before adding a new constraint:
IF OBJECT_ID('CHK_Student_ID_LENGTH') IS NOT NULL
ALTER TABLE Student DROP CONSTRAINT CHK_Student_ID_LENGTH
IF OBJECT_ID('CHK_Student_ID_LENGTH') IS NULL
ALTER TABLE Student ADD CONSTRAINT ...
More about ALTER TABLE https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql?view=sql-server-ver15

Is there inconsistency in PostgreSQL syntax of adding constraints to a table?

From PostgreSQL document
To add a constraint, the table constraint syntax is used. For example:
ALTER TABLE products ADD CHECK (name <> '');
ALTER TABLE products ADD CONSTRAINT some_name UNIQUE (product_no);
ALTER TABLE products ADD FOREIGN KEY (product_group_id) REFERENCES product_groups;
To add a not-null constraint, which cannot be written as a table
constraint, use this syntax:
ALTER TABLE products ALTER COLUMN product_no SET NOT NULL;
Why the word after ADD differ for constraints of different kinds?
Why does unique constraint has a more generic ADD CONSTRAINT some_name than check and foreign key?
Why is not null constraint specified by ALTER COLUMN, instead of ADD CONSTRAINT some_name NOT NULL (col_name)?
Is there inconsistency in PostgreSQL syntax of adding constraints to a table?
Does this belong to the SQL standard?
The word after ADD differs so the database knows what you mean. E.g. CHECK introduces a generic boolean condition; UNIQUE is followed by a list of column names; FOREIGN KEY is followed by a column name, REFERENCES, and a target table/column. Without these keywords it would be ambiguous which kind of constraint you mean.
The CONSTRAINT constraint_name syntax is not limited to unique constraints. See the definition of column_constraint and table_constraint in https://www.postgresql.org/docs/10/static/sql-createtable.html; both allow an optional leading CONSTRAINT constraint_name to name the constraint.
As for NOT NULL, see https://www.postgresql.org/docs/10/static/ddl-constraints.html#id-1.5.4.5.6:
A not-null constraint is always written as a column constraint. A not-null constraint is functionally equivalent to creating a check constraint CHECK (column_name IS NOT NULL), but in PostgreSQL creating an explicit not-null constraint is more efficient. The drawback is that you cannot give explicit names to not-null constraints created this way.
I assume not-null constraints are a special case internally, allowing for better optimization than a generic CHECK constraint, which can use any boolean expression.
We cant use add constraint syntax for Not Null. You have to use modify column syntax to add not null
eg.
alter table modify ( not null);

POSTGRES - Handling several ON CONFLICT constraints/indexes

Have the following in the table where:
CONSTRAINT unique_position UNIQUE (id,city,type)
and
CREATE UNIQUE INDEX unique_position_sat_null ON public."position" (id,city) where type is null
on insert conflict there is currently:
ON CONFLICT ON CONSTRAINT unique_position DO UPDATE SET
.....
How can I incorporate both unique_position and unique_position_sat_null into ON CONFLICT ON CONSTRAINT
Tried:
ON CONFLICT ON CONSTRAINT unique_position DO UPDATE SET
.....,
ON CONFLICT ON CONSTRAINT unique_position_sat_null DO UPDATE SET
.....,
and
ON CONFLICT ON CONSTRAINT unique_position and unique_position_sat_null DO UPDATE SET
.....,
Thank you.
Unfortunately, unique indexes and unique constraints are not the same things in Postgres.
When you define a unique index, not constraint, Postgres doesn't create a constraint with the same name (in case of collisions during INSERTs it will produce error "unique constraint violation" mentioning index' name, but this is a minor bug, see https://www.postgresql.org/message-id/flat/CAH2-Wzn-uXcLgC5uFbqe2rUfmJWP9AxKnMKAEgqU26hbURxk5A%40mail.gmail.com#CAH2-Wzn-uXcLgC5uFbqe2rUfmJWP9AxKnMKAEgqU26hbURxk5A#mail.gmail.com)
So you cannot use index name like it is a constraint name.
You could do ALTER TABLE .. ADD CONSTRAINT .. UNIQUE, but it cannot be unique.
So this can be considered as a not yet implemented feature in Postgres -- either "ON CONFLICT" clause needs to learn how to use index names or ALTER TABLE .. ADD CONSTRAINT .. UNIQUE needs to be patched to allow partial constraints.
I suggest discussing it in pgsql-hackers# mailing list (e.g. if you answer thread mentioned above, explaining your problem, it would be awesome).

DB2 UNIQUE Constraint that is Case Insensitive

How do I create a unique constraint on a table?
I tried doint this but it chokes on UPPER.
ALTER TABLE MY_TABLE ADD UNIQUE(UPPER(MY_COL))
Thanks,
If you want to use a function you would need to use the CREATE INDEX statement. The keyword "unique" makes it a unique constraint.
CREATE UNIQUE INDEX MyUpperIndex ON MY_TABLE(UPPER(MY_COL))

Check constraint on existing column with PostgresQL

I'm trying to put check constraint on existing column.
Is there any way to achieve this from PostgreSQL?
Use alter table to add a new constraint:
alter table foo
add constraint check_positive check (the_column > 0);
More details and examples are in the manual:
http://www.postgresql.org/docs/current/static/sql-altertable.html#AEN70043
Edit
Checking for specific values is done in the same way, by using an IN operator:
alter table foo
add constraint check_positive check (some_code in ('A','B'));
If you are okay with (or want) Postgres to generate a constraint name you can use the following shorthand syntax.
ALTER TABLE foo
ADD CHECK (column_1 > 2);
You can add a new constraint with with alter table command. From documentation this example:
ALTER TABLE distributors
ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5) NO INHERIT;
You will have to replace constraint name as well as table name and content by your local requirements.
This should do it:
create table test (
id serial
);
alter table test
add constraint id_not_null
check (id is not null);