CREATE TABLE with column of certain value if other column has a value - sql

Im trying to create table that has two certain columns. In one of them (deliverer) there are a few possible values. In second, there are few possible values as well. Value in second column is required only if deliverer has value 'A', otherwise it can be (and should be in fact a NULL)
this is my atempt
CREATE TABLE dict_shipping_types (
id bigserial NOT NULL,
deliverer varchar(50) NOT NULL,
gage varchar(1)
)
;
ALTER TABLE dict_shipping_types
ADD CONSTRAINT CHK_dict_shipping_types_deliverer CHECK (deliverer IN ('CompanyA','CompanyB','CompanyC'))
;
ALTER TABLE dict_shipping_types
ADD CONSTRAINT CHK_dict_shipping_types_gage_not_null
CHECK (
(DELIVERER='CompanyA' AND GAGE IN ('A','B','C') AND GAGE != NULL ) OR
(DELIVERER!='CompanyA' AND GAGE=NULL)
)
;
ALTER TABLE dict_shipping_types ADD CONSTRAINT PK_dict_shipping_types
PRIMARY KEY (id)
;
Test Queries
INSERT INTO dict_shipping_types(deliverer) VALUES('CompanyA')
INSERT INTO dict_shipping_types(deliverer,GAGE) VALUES('CompanyB','A')
INSERT INTO dict_shipping_types(deliverer,GAGE) VALUES('CompanyA','D')
All of them should fail, but only third one does. How in check i can allow NULL or NOT NULL values?

You can fix it with NOT NULL/IS NOT NULL instead of !=NULL/=NULL
CREATE TABLE dict_shipping_types (
id bigserial NOT NULL,
deliverer varchar(50) NOT NULL,
gage varchar(1)
)
;
ALTER TABLE dict_shipping_types
ADD CONSTRAINT CHK_dict_shipping_types_deliverer CHECK (deliverer IN ('CompanyA','CompanyB','CompanyC'))
;
ALTER TABLE dict_shipping_types
ADD CONSTRAINT CHK_dict_shipping_types_gage_not_null
CHECK (
(DELIVERER='CompanyA' AND GAGE IN ('A','B','C') AND GAGE is not NULL) or
(DELIVERER!='CompanyA' AND GAGE is NULL)
);
ALTER TABLE dict_shipping_types ADD CONSTRAINT PK_dict_shipping_types
PRIMARY KEY (id)
;

Related

Add a reference to a postgrest table

I want to alter the artist_label to be label_id BIGINT NOT NULL REFERENCES label(id) like how it is in the album_label table.
CREATE TABLE label (
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
parent_label_id BIGINT REFERENCES label(id)
);
CREATE TABLE album_label (
id BIGSERIAL PRIMARY KEY,
album_id TEXT NOT NULL UNIQUE,
label_id BIGINT NOT NULL REFERENCES label(id)
);
CREATE INDEX album_label_idx ON album_label(label_id);
CREATE INDEX album_uid_idx ON album_label(id)
CREATE TABLE artist_label (
artist_id VARCHAR(60) NOT NULL,
label_id BIGINT NOT NULL,
PRIMARY KEY (artist_id, label_id)
);
CREATE INDEX artist_label_idx ON artist_label(label_id);
If you haven't created the tables yet, you could modify the creation script and add that clause.
If you're asking how to modify the table after its creation, you can use an alter table statement:
ALTER TABLE artist_label
ADD CONSTRAINT artist_label_fk FOREIGN KEY (label_id) REFERENCES label(id)
SQLFiddle Example

SQL constraint: two attributes, at least one foreign key match on same table

I have a table of phone numbers owned by a company, and a table of phone call records. Every call record includes (non-null) source and destination numbers. I am given the integrity constraint that either the source number or the destination number, but not both, are allowed to be numbers that are not in the phone number table (because they are numbers not owned by this company). In other words, I need to ensure that at least one of them is a foreign key to the phone number table.
create table phonenumber (
phonenum numeric(10,0) not null,
primary key (phonenum)
);
create table call_record (
URID varchar(20) not null,
c_src numeric(10,0) not null,
c_dst numeric(10,0) not null,
primary key (URID)
);
The following sounds like what I want but isn't valid SQL:
constraint call_constraint check (
foreign key (c_src) references phonenumber (phonenum) or
foreign key (c_dst) references phonenumber (phonenum)
)
Is there a way to specify this in DDL? If not, how would I write a trigger to enforce this?
Edited:
Here is another idea using DDL and not using trigger:
create table phonenumber (
phonenum numeric(10,0) not null,
primary key (phonenum)
);
Create a function to validate foreign key "by hand".
CREATE OR REPLACE FUNCTION call_check(p_src NUMBER, p_dst NUMBER) RETURN VARCHAR2 DETERMINISTIC IS
BEGIN
FOR x IN (SELECT COUNT(*) c
FROM (SELECT 1
FROM phonenumber
WHERE phonenum = p_src
UNION ALL
SELECT 1
FROM phonenumber
WHERE phonenum = p_dst)) LOOP
IF x.c>=1 AND x.c <= 2 THEN
RETURN 'OK';
END IF;
END LOOP;
RETURN 'NOK';
END;
If you're on 11g and up, then add virtual column and add check on that column
--drop table call_record
create table call_record (
URID varchar(20) not null,
c_src numeric(10,0) not null,
c_dst numeric(10,0) not null,
call_check_col GENERATED ALWAYS AS (call_check(c_src, c_dst)),
primary key (URID)
);
ALTER TABLE call_record ADD CONSTRAINT call_check_con CHECK (call_check_col='OK');
Let's test
SQL> INSERT INTO phonenumber VALUES ('123');
1 row inserted
SQL> INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C1', '123', '321');
1 row inserted
SQL> INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C3', '123', '123');
1 row inserted
SQL> INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C2', '321', '321');
INSERT INTO call_record (urid, c_src, c_dst) VALUES ('C2', '321', '321')
ORA-02290: check constraint (TST.CALL_CHECK_CON) violated

primary key of new row automatically goes to 2nd table where it's a foreign key in a new row

This is my 1st table
CREATE TABLE [dbo].[Booking_Date]
(
[Book_ID] INT IDENTITY (1, 1) NOT NULL,
[Book_Checkin_Date] DATETIME NULL,
[Book_Checkout_date] DATETIME NULL,
[Adults] INT NULL,
[Children] INT NULL,
CONSTRAINT [PK_Booking_Date]
PRIMARY KEY CLUSTERED ([Book_ID] ASC)
);
And this is my 2nd table
CREATE TABLE [dbo].[Room_Detail]
(
[R_D_ID] INT IDENTITY (1, 1) NOT NULL,
[Cust_ID] INT NULL,
[Book_ID] INT NULL,
[Room_ID] INT NULL,
[Room_Price] MONEY NULL,
PRIMARY KEY CLUSTERED ([R_D_ID] ASC),
CONSTRAINT [FK_Room_Detail_Customer]
FOREIGN KEY ([Cust_ID]) REFERENCES [dbo].[Customer] ([Cust_ID]),
CONSTRAINT [FK_Room_Detail_Booking_Date]
FOREIGN KEY ([Book_ID]) REFERENCES [dbo].[Booking_Date] ([Book_ID]),
CONSTRAINT [FK_Room_Detail_Room]
FOREIGN KEY ([Room_ID]) REFERENCES [dbo].[Room] ([Room_ID])
);
When I insert data into my 1st table a with booking date, then primary key of that data automatically is inserted into the 2nd table that is Room Detail in the Book_ID column
If you want to do this in T-SQL / SQL Server, you can use an AFTER INSERT trigger on the Booking_Date table - something like this:
CREATE TRIGGER trgInsertBookingDate
ON dbo.Booking_Date
AFTER INSERT
AS
-- for each row newly inserted into "Booking_Date",
-- insert a new (empty) row into "Room_Detail"
INSERT INTO dbo.Room_Detail(Book_ID)
SELECT i.Book_ID
FROM Inserted i
So every time you insert one or multiple row(s) into Booking_Date, a new (more or less empty) row will be inserted into Room_Detail for each of those new rows inserted. Since you don't have any other information available, you can only set the Book_ID column of Room_Detail in the trigger - the other columns will have to somehow be specified / filled later

Oracle - How do I create a table that has an autoincrementing unique key for the ID

This is the first time that I've use oracle SQL and I'm having a problem creating tables with a unique key.
I don't understand why this auto-incrementing id is not working:
ID BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
The next question I have is why I am getting an error in each of my statements:
ORA-00922: missing or invalid option
Here is my code:
--
-- Sequence for aout incrment
--
CREATE SEQUENCE IF NOT EXISTS AUTO_INC_SEQ
START WITH 1
INCREMENT BY 1;
--
-- Table Person
--
CREATE TABLE IF NOT EXISTS FITNESS_PERSON
(
ID NUMBER NOT NULL PRIMARY KEY,
FIRST_NAME VARCHAR NOT NULL,
LAST_NAME VARCHAR NOT NULL,
NICK_NAME VARCHAR NOT NULL,
DATE_BIRTH DATE NOT NULL,
PASSWORD VARCHAR NOT NULL,
CONSTRAINT UNIQUE(NICK_NAME)
);
--
-- Table BMR
--
CREATE TABLE IF NOT EXISTS FITNESS_BMR
(
ID NUMBER NOT NULL PRIMARY KEY,
VALUE FLOAT NOT NULL,
VALUE_DATE DATE NOT NULL
);
--
-- M:N for BMR and Person
--
CREATE TABLE IF NOT EXISTS FITNESS_BMR_PERSON
(
BMR_ID NUMBER NOT NULL,
PERSON_ID NUMBER NOT NULL,
FOREIGN KEY(BMR_ID) REFERENCES FITNESS_BMR(ID),
FOREIGN KEY(PERSON_ID) REFERENCES FITNESS_PERSON(ID),
CONSTRAINT BMR_PER PRIMARY KEY(BMR_ID, PERSON_ID)
);
What's the right way to do this (create a table and with an auto-incrementing key that is unique).
You can use a table, a sequence to generate unique ID values and a trigger.
For example:
Table:
CREATE Table FITNESS_BMR
(
ID NUMBER NOT NULL PRIMARY KEY,
VALUE FLOAT NOT NULL,
VALUE_DATE DATE NOT NULL
);
Sequence: create sequence t1_seq start with 1 increment by 1 nomaxvalue;
Trigger:
CREATE OR REPLACE TRIGGER test_trigger
BEFORE INSERT
ON FITNESS_BMR
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT t1_seq.nextval INTO :NEW.ID FROM dual;
END;
/

Reusing a constraint while creating a table

While creating a table how can I reuse a constraint that has been mentioned for a previous column?
create table ticket_details(
from_stn char(3)
constraint chk check(from_stn in ('vsh','mas','ndl'))
constraint nn NOT NULL,
to_stn char(3)
constraint nn1 NOT NULL, (instead of crea)
seat_no number(3)
constraint PK primary key,
);
A domain constraint will be enforced on any instance of the domain. Also: upon change, you'll have to change it in only one place. (the syntax might differ slightly between implementations)
CREATE DOMAIN THE_STN CHAR(3) constraint THE_STN_check_da_value check(VALUE in ('vsh','mas','ndl'))
;
CREATE table ticket_details
( seat_no INTEGER NOT NULL PRIMARY KEY
, from_stn THE_STN NOT NULL
, to_stn THE_STN
);
INSERT INTO ticket_details(seat_no,from_stn,to_stn) VALUES (1, 'vsh', 'ndl' ); -- succeeds
INSERT INTO ticket_details(seat_no,from_stn,to_stn) VALUES (2, 'vsh', NULL ); -- succeeds
INSERT INTO ticket_details(seat_no,from_stn,to_stn) VALUES (2, 'lol', 'mas' ); -- fails
Reusing a constraint for another column is not possible. You have to define it for other column if you want