Use of CHECK constraint in redshift tables - sql

I have a redshift table with a column id which has bigint data type.
I want to add a constraint to check if the inserted value is positive and fail insertion if it is negative
CREATE TABLE IF NOT EXISTS public.new_table
(
id BIGINT NOT NULL ENCODE az64
, CONSTRAINT CHK check ( id > 0 )
)
When I ran the query , I am getting the error
Amazon Invalid operation: CREATE TABLE CHECK constraint is not supported; [SQL State=0A000, DB Errorcode=500310]
Any solve for this issue?

Related

Postgres breaking null constraint on a serial column

I have a table that I create independently, the primary key is set with the serial type and a sequence applied to the table, but when I try to insert a value a NULL CONSTRAINT error is thrown and the return looks like null was passed, am I missing something in the INSERT statement?
SQL for table generation:
DROP TABLE IF EXISTS public."Team" CASCADE;
CREATE TABLE public."Team" (
"IdTeam" serial PRIMARY KEY,
name text NOT null,
CONSTRAINT "pKeyTeamUnique" UNIQUE ("IdTeam")
);
ALTER TABLE public."Team" OWNER TO postgres;
DROP SEQUENCE IF EXISTS public."Team_IdTeam_seq" CASCADE;
CREATE SEQUENCE public."Team_IdTeam_seq"
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public."Team_IdTeam_seq" OWNER TO postgres;
ALTER SEQUENCE public."Team_IdTeam_seq" OWNED BY public."Team"."IdTeam";
SQL for insert :
INSERT INTO public."Team" (name) values ('Manchester Untited');
The returning error:
ERROR: null value in column "IdTeam" violates not-null constraint
DETAIL: Failing row contains (null, Manchester Untited).
SQL state: 23502
I am baffled. Why are you trying to define your own sequence when the column is already defined as serial?
Second, a primary key constraint is already unique. There is no need for a separate unique constraint.
Third, quoting identifiers just makes the code harder to write and to read.
You can just do:
DROP TABLE IF EXISTS public.Team CASCADE;
CREATE TABLE public.Team (
IdTeam serial PRIMARY KEY,
name text NOT null
);
INSERT INTO public.Team (name)
VALUES ('Manchester Untited');
Dropping the sequence causes the default definition for the IdTeam column to be dropped. After recreating the sequence you will have to recreate the default definition.

How to name NOT NULL constraint in CREATE TABLE query

For a test tomorrow we're told to name our constraints
I know it's possible to create a constraint when you use ALTER TABLE
but can you add a name to a not null constraint when you CREATE TABLE?
f.e.
CREATE TABLE test (
test1 VARCHAR
CONSTRAINT nn_test1 NOT NULL (test1)
)
I get an error when trying to run this query. Am I writing it wrong?
The error I get is
ERROR: syntax error at or near "NOT"
LINE 3: CONSTRAINT nn_test1 NOT NULL (test1))
^
SQL state: 42601
Character: 56
You have two options to define a named not null constraint:
Inline with the column:
CREATE TABLE test
(
test1 VARCHAR CONSTRAINT nn_test1 NOT NULL,
test2 integer --<< no comma because it's the last column
);
Or at the end of columns as an out-of-line constraint. But then you need a check constraint:
CREATE TABLE test
(
test1 VARCHAR,
test2 integer, --<< comma required after the last column
constraint nn_test1 check (test1 is not null)
);
This has become irrelevant, since you're not using SQL Server
First of all, you should always specify a length for a VARCHAR. Not doing so (in SQL Server variables, or parameters) may result in a string of just exactly ONE character in length - typically NOT what you want.
Then, you need to just specify the NOT NULL - there's no need to repeat the column name (actually this is the error) - if you're specifying the CONSTRAINT "inline" with the column definition (which is a perfectly legal and in my opinion the preferred way of doing this).
Try this code:
CREATE TABLE test
(
test1 VARCHAR(50)
CONSTRAINT nn_test1 NOT NULL
)
At least this is the CREATE TABLE statement that works in T-SQL / SQL Server - not sure about PostgreSQL (don't know it well enough, don't have it at hand to test right now).
I, a_horse_with_no_name, the two syntax:
constraint nn_test1 check (test1 is not null)
and
test1 VARCHAR CONSTRAINT nn_test1 NOT NULL
are equivalent ? performance correctly ecc.
Because in first case the SQL server exception return the name nn_test so the system know exactly error.

Adding a NOT NULL column to a Redshift table

I'd like to add a NOT NULL column to a Redshift table that has records, an IDENTITY field, and that other tables have foreign keys to.
In PostgreSQL, you can add the column as NULL, fill it in, then ALTER it to be NOT NULL.
In Redshift, the best I've found so far is:
ALTER TABLE my_table ADD COLUMN new_column INTEGER;
-- Fill that column
CREATE TABLE my_table2 (
id INTEGER IDENTITY NOT NULL SORTKEY,
(... all the fields ... )
new_column INTEGER NOT NULL,
PRIMARY KEY(id)
) DISTSTYLE all;
UNLOAD ('select * from my_table')
to 's3://blah' credentials '<aws-auth-args>' ;
COPY my_table2
from 's3://blah' credentials '<aws-auth-args>'
EXPLICIT_IDS;
DROP table my_table;
ALTER TABLE my_table2 RENAME TO my_table;
-- For each table that had a foreign key to my_table:
ALTER TABLE another_table ADD FOREIGN KEY(my_table_id) REFERENCES my_table(id)
Is this the best way of achieving this?
You can achieve this w/o having to load to S3.
modify the existing table to create the desired column w/ a default value
update that column in some way (in my case it was copying from another column)
create a new table with the column w/o a default value
insert into the new table (you must list out the columns rather than using (*) since the order may be the same (say if you want the new column in position 2)
drop the old table
rename the table
alter table to give correct owner (if appropriate)
ex:
-- first add the column w/ a default value
alter table my_table_xyz
add visit_id bigint NOT NULL default 0; -- not null but default value
-- now populate the new column with whatever is appropriate (the key in my case)
update my_table_xyz
set visit_id = key;
-- now create the new table with the proper constraints
create table my_table_xzy_new
(
key bigint not null,
visit_id bigint NOT NULL, -- here it is not null and no default value
adt_id bigint not null
);
-- select all from old into new
insert into my_table_xyz_new
select key, visit_id, adt_id
from my_table_xyz;
-- remove the orig table
DROP table my_table_xzy_events;
-- rename the newly created table to the desired table
alter table my_table_xyz_new rename to my_table_xyz;
-- adjust any views, foreign keys or permissions as required

Postgres: Problems using insert with select

I have a table defined like this:
CREATE TABLE wp_master (
gid integer NOT NULL DEFAULT nextval('wp_master_gid_seq'::regclass),
name character varying(80),
....
type integer DEFAULT 4,
CONSTRAINT p_key PRIMARY KEY (gid),
);
I want to insert data into the table from another table so I
insert into wp_master ( name, .... type) select "NAME", ...., 1 from ."Tiri2011";
but I get the error:
ERROR: duplicate key value violates unique constraint "p_key"
DETAIL: Key (gid)=(2) already exists.
Why is postgres trying to put anything into the gid field when I have explicitly not included it in the list of columns? I assumed that gid pick up its value from the sequence.
Russell
Is is trying to insert the next value of the wp_master_gid_seq sequence. Declaring an id column as serial (auto-increment) will create a sequence which has a stored value of the last inserted id which was auto-incremented. If at anytime you inserted a gid value manually, it bypassed the sequence and the autoincrement function may become broken, because the sequence value did not get updated accordingly.
The easiest way to fix it is to change the value of the sequence to the (max gid value of your table) + 1. Just execute this once and you should be ok
select setval('wp_master_gid_seq', coalesce((select max(id)+1 from wp_master), 1), false)

CHECK CONSTRAINT on multiple columns

I use SQL Server 2008
I use a CHECK CONSTRAINT on multiple columns in the same table to try to validate data input.
I receive an error:
Column CHECK constraint for column
'AAAA' references another column,
table 'XXXX'.
CHECK CONSTRAINT does not work in this way.
Any other way to implement this on a single table without using FK?
Thanks
Here an example of my code
CREATE TABLE dbo.Test
(
EffectiveStartDate dateTime2(2) NOT NULL,
EffectiveEndDate dateTime2(2) NOT NULL
CONSTRAINT CK_CmsSponsoredContents_EffectiveEndDate CHECK (EffectiveEndDate > EffectiveStartDate),
);
Yes, define the CHECK CONSTRAINT at the table level
CREATE TABLE foo (
bar int NOT NULL,
fred varchar(50) NOT NULL,
CONSTRAINT CK_foo_stuff CHECK (bar = 1 AND fred ='fish')
)
You are declaring it inline as a column constraint
...
fred varchar(50) NOT NULL CONSTRAINT CK_foo_fred CHECK (...)
...
Edit, easier to post than describe. Fixed your commas.
CREATE TABLE dbo.Test
(
EffectiveStartDate dateTime2(2) NOT NULL,
EffectiveEndDate dateTime2(2) NOT NULL, --need comma
CONSTRAINT CK_CmsSponsoredContents_EffectiveEndDate CHECK (EffectiveEndDate > EffectiveStartDate) --no comma
);
Of course, the question remains are you using a CHECK constraint where it should be an FK constraint...?
Check constraints can refer to a single column or to the whole record.
Use this syntax for record-level constraints:
ALTER TABLE MyTable
ADD CONSTRAINT MyCheck
CHECK (...your check expression...)
You can simply apply your validation in a trigger on the table especially that either way the operation will be rolled back if the check failed.
I found it more useful for CONSTRAINT using case statements.
ALTER TABLE dbo.ProductStock
ADD
CONSTRAINT CHK_Cost_Sales
CHECK ( CASE WHEN (IS_NOT_FOR_SALE=0 and SAL_CPU <= SAL_PRICE) THEN 1
WHEN (IS_NOT_FOR_SALE=1 ) THEN 1 ELSE 0 END =1 )