sql- not null with default, check constraint - sql

I have created a table and I'm asked to add a constraint to a column called no_semesters. the condition is that the no has to be >= 0 and it should be not null with default, and the default value is 6. When I run this statement:
INSERT INTO PREMIERD08/PGM (PGM_ID, PGM_NAME)
VALUES('CPD', 'COMPUTER PROGRAMMING')
I get an error message saying column - no_semesters cant be null. why wont it set to the default value which is 6?
this was the statement -
CREATE TABLE PREMIERD08/PGM (
PGM_ID CHAR(3) NOT NULL,
PGM_NAME CHAR(40) NOT NULL,
NO_SEMESTERS NUMERIC ( 1) NOT NULL WITH DEFAULT 6,
CONSTRAINT PGM_PGM_NAME_UK UNIQUE (PGM_NAME),
CONSTRAINT PGM_PGM_ID_CK CHECK (PGM_ID IN ('CPA', 'CPD') ),
CONSTRAINT PGM_PGM_ID_PK PRIMARY KEY (PGM_ID), CONSTRAINT PGM_NO_SEMESTERS_CK CHECK (NO_SEMESTERS >= 0)
)

Your code works in Db2 (for LUW) - the only thing to change is the table name needs to be in "" because of the /
CREATE TABLE "PREMIERD08/PGM" .....
INSERT INTO "PREMIERD08/PGM" (PGM_ID, PGM_NAME)
VALUES('CPD', 'COMPUTER PROGRAMMING')

Related

Upsert (merge) for updating record if it exists and inserting otherwise

I am trying to write a DB2 query that allows me to either update a record if it already exists but if it does not exist it should be inserted. I wrote the following query that should accomplish this:
MERGE INTO OA1P.TLZ712A1 AS PC
USING (
SELECT * FROM OA1P.TLZ712A1
WHERE CALENDAR_ID=13 AND
"PACKAGE"='M2108'
) PC2
ON (PC.ID_PACKAGE_CALENDAR=PC2.ID_PACKAGE_CALENDAR)
WHEN MATCHED THEN
UPDATE SET ACT_DATE = '31.12.2021'
WHEN NOT MATCHED THEN
INSERT ("PACKAGE", ACT_DATE, CALENDAR_ID, PREPTA, MIXED) VALUES ('M2108', '31.12.2021', 13, 0, 0)
This query should attempt to check if a record already exists for the selection criteria. Updating a record seems to be working fine but I am not able to get the "WHEN NOT MATCHED" part to work and inserting a new record. Anyone able to provide some assistance?
The table is used to save the activation date of a certain software package. PACKAGE is the reference to the package table containing the name of the package (eg. "M2108"). CALENDAR_ID refers to a system where the software package will be activated. The actual date is stored in ACT_DATE.
Did not manage to get the DDL into SQLFiddle so I have to provide it here:
CREATE TABLE OA1P.TLZ712A1 (
ID_PACKAGE_CALENDAR INTEGER DEFAULT IDENTITY GENERATED BY DEFAULT NOT NULL,
CALENDAR_ID INTEGER,
"PACKAGE" VARCHAR(10) NOT NULL,
ACT_DATE DATE NOT NULL,
PREPTA SMALLINT DEFAULT 0 NOT NULL,
MIXED SMALLINT DEFAULT 0 NOT NULL,
"COMMENT" VARCHAR(60) NOT NULL,
LAST_MODIFIED_PID CHAR(7) NOT NULL,
ST_STARTID TIMESTAMP NOT NULL,
ST_FROM TIMESTAMP NOT NULL,
ST_TO TIMESTAMP NOT NULL,
CONSTRAINT TLZ712A1_PK PRIMARY KEY (ID_PACKAGE_CALENDAR),
CONSTRAINT CALENDAR FOREIGN KEY (CALENDAR_ID) REFERENCES OA1P.TLZ711A1(ID_CALENDAR) ON DELETE RESTRICT,
CONSTRAINT "PACKAGE" FOREIGN KEY ("PACKAGE") REFERENCES OA1P.TLZ716A1(NAME) ON DELETE RESTRICT
);
CREATE UNIQUE INDEX ILZ712A0 ON OA1P.TLZ712A1 (ID_PACKAGE_CALENDAR);
If your goal is to set ACT_DATE to 31.12.2021 if a row is found with PACKAGE = M2108 and CALENDAR_ID = 13 and if no row is found with these values then insert it, then this could be the answer
MERGE INTO OA1P.TLZ712A1 AS PC
USING (
VALUES ('M2108', 13, date '31.12.2021')
) PC2 ("PACKAGE", CALENDAR_ID, ACT_DATE)
ON (PC."PACKAGE", PC.CALENDAR_ID) = (PC2."PACKAGE", PC2.CALENDAR_ID)
WHEN MATCHED THEN
UPDATE SET ACT_DATE = PC2.ACT_DATE
WHEN NOT MATCHED THEN
INSERT ("PACKAGE", ACT_DATE, CALENDAR_ID, PREPTA, MIXED) VALUES (PC2."PACKAGE", PC2.ACT_DATE, PC2.CALENDAR_ID, 0, 0)

PostgreSQL Custom not null constraint

I want to add a NOT NULL contstraint to one of my table fields but only when another field has a certain value.
So I have a services table:
services:
- id
- professional_id
- is_master
I want to write a SQL constraint that whenever is_master is false professional_id cannot be null. I've tried things like:
CREATE TABLE "services" (
"id" text NOT NULL,
"professional_id" text REFERENCES professionals ON DELETE CASCADE ON UPDATE CASCADE,
EXCLUDE USING gist (
professional_id WITH =,
) WHERE (NOT is_master),
"is_master" boolean NOT NULL DEFAULT false,
PRIMARY KEY ("id")
);
What is the correct way to write this SQL?
You can do this with a check constraint. A simple one is:
constraint chk_services_master_professions
check (is_master or professional_id is not null)
Note: This version assumes that is_master is never NULL -- or that NULL is equivalent to "false".
check (not is_master and professional_id is not null or is_master)
You could use CHECK constraint:
CREATE TABLE "services" (
"id" text NOT NULL,
"professional_id" text
CHECK (CASE WHEN "is_master" IS FALSE AND "professional_id" IS NULL
THEN FALSE ELSE TRUE END), -- and rest of FK
"is_master" boolean NOT NULL DEFAULT false,
PRIMARY KEY ("id")
);
Rextester Demo
INSERT INTO services
VALUES (1,1, FALSE);
INSERT INTO services
VALUES (2,1, true);
INSERT INTO services
VALUES (3, null, true);
INSERT INTO services
VALUES (4, null, false);
23514: new row for relation "services" violates check constraint "services_check"

postgres syntax error at or near "ON"

I created this table:
CREATE TABLE IF NOT EXISTS config_activity_log
(
id serial primary key,
activity_name varchar(100) NOT NULL,
last_config_version varchar(50) NOT NULL,
activity_status varchar(100) NOT NULL DEFAULT 'Awaiting for cofman',
cofman_last_update bigint NOT NULL DEFAULT -1,
is_error boolean DEFAULT FALSE,
activity_timestamp timestamp DEFAULT current_timestamp
);
I try to run this postgres script:
INSERT INTO config_activity_log
(activity_name, last_config_version, activity_status)
VALUES
('test awating deployment','5837-2016-08-24_09-12-22', 'Awaiting for deployment')
ON CONFLICT (activity_name)
DO UPDATE SET
activity_status = EXCLUDED.activity_status
why do i get this syntax error?
psql:upsert_test_log.sql:7: ERROR: syntax error at or near "ON"
LINE 5: ON CONFLICT (activity_name)
Supported Version
Per #klin's comment above, ON CONFLICT is only supported from PostgreSQL 9.5 onwards.
If you're on an earlier version, there's some great info in this answer: https://stackoverflow.com/a/17267423/361842
Unique Constraint
Add a unique index on activity_name. At present there's no constraints on that column, so there's no possibility for a conflict on that column.
CREATE UNIQUE INDEX UK_config_activity_log__activity_name
ON config_activity_log (activity_name);
If, however, you don't want that column to be unique, what conflict are you envisaging / what's the issue you're hoping to resolve with the on conflict action?
See conflict_target in https://www.postgresql.org/docs/9.5/static/sql-insert.html#SQL-ON-CONFLICT
An alternative syntax is to modify your create statement to include the unique condition there; e.g.
CREATE TABLE IF NOT EXISTS config_activity_log
(
id serial primary key,
activity_name varchar(100) NOT NULL UNIQUE,
last_config_version varchar(50) NOT NULL,
activity_status varchar(100) NOT NULL DEFAULT 'Awaiting for cofman',
cofman_last_update bigint NOT NULL DEFAULT -1,
is_error boolean DEFAULT FALSE,
activity_timestamp timestamp DEFAULT current_timestamp
);
According to the error code, your version does not support ON CONFLICT.
On PostreSQL 9.6 the error message is -
[Code: 0, SQL State: 42P10] ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification

Check if a value appears only once in a column

I want to create a table for managing versions of parameters...
In this table there is a column of type char that lets me know what version I have to use :
create table PARAMETERS_VERSION (
ID number not null,
VERSION number not null,
DATE_START date not null,
DATE_END date check(DATE_START <= DATE_END) not null
ISUSED char(1) check(ISUSED in ('Y','N')) not null,
constraint PARAMETERS_VERSION_VERSION_PK primary key (ID),
constraint PARAMETERS_VERSION_VERSION_UK unique (ISUSED)
);
How to define a unique constraint on the column ISUSED to have only a single row with the value 'Y' (and the others with 'N') ?
By the way, is my check constraint on DATE_END is correct ?
Oracle doesn't quite support partial or filtered indexes. Instead, you can use a functional index with some cleverness:
create unique index idx_parametersversion_isused
on parameters_version(case when is_used = 'Y' then -1 else id end);
That is, when is_used has any value other than Y, then the primary key is used. When it is Y, then a constant is used, so two values will conflict.

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 )