Constraint to check if time greater than 9 am - sql

How to check time entry only so that any entry before is not acceptable?
CREATE TABLE demo.event(
ecode CHAR(4) UNIQUE NOT NULL PRIMARY KEY,
edesc VARCHAR(20) NOT NULL,
elocation VARCHAR(20) NOT NULL,
edate DATE NOT NULL
CONSTRAINT date_check CHECK(edate BETWEEN '2016/04/01' AND '2016/04/30'),
etime TIME NOT NULL
CONSTRAINT time_check CHECK(etime (HOUR > '08:00:00')),
emax SMALLINT NOT NULL
CONSTRAINT emax_check CHECK(emax >=1 OR emax<=1000)
);
The above code gave me an error
ERROR: column "hour" does not exist

To write a time literal, you need to use the keyword time not hour:
CONSTRAINT time_check CHECK(etime > TIME '08:00:00'),
so any entry before 9:00 am not acceptable.
contradicts the 08:00:00' you have used, > TIME '08:00:00' will allow 08:00:01 (one second after 8am). If you really only want to allowed values after 9am, then use:
CONSTRAINT time_check CHECK(etime > TIME '09:00:00'),
You should also use proper ISO formatted dates to avoid any ambiguity:
CONSTRAINT date_check CHECK(edate BETWEEN DATE '2016-04-01' AND DATE '2016-04-30')
More details on the proper syntax for date and time literals can be found in the manual:
http://www.postgresql.org/docs/current/static/datatype-datetime.html#DATATYPE-DATETIME-INPUT

Related

CUSTOM UNIQUE CHECK POSTGRES

I am working on a task where I need to store the interviewer's time slot in the table INTERVIEW_SLOT. The table schema is like this:
CREATE TABLE INTERVIEW_SLOT (
ID SERIAL PRIMARY KEY NOT NULL,
INTERVIEWER INTEGER REFERENCES USERS(ID) NOT NULL,
START_TIME TIMESTAMP NOT NULL, -- start time of interview
END_TIME TIMESTAMP NOT NULL, -- end time of interview
IS_BOOKED BOOL NOT NULL DEFAULT 'F', -- slot is booked by any candidate or not
CREATED_ON TIMESTAMP,
-- interviewer can't give the same slot twice
CONSTRAINT UNIQUE_INTERVIEW_SLOT UNIQUE (start_time, INTERVIEWER)
);
We want to ensure that the interviewer can not give the same slot twice but the problem is with second and millisecond values of start_time. I want the UNIQUE_INTERVIEW_SLOT constant like this:
UNIQUE_INTERVIEW_SLOT UNIQUE(TO_TIMESTAMP(start_time::text, 'YYYY-MM-DD HH24:MI'), INTERVIEWER)
Is there any way to add a unique constraint that ignores the second and millisecond value?
You are looking for an exclusion constraint
create table interview_slot
(
id integer primary key generated always as identity,
interviewer integer references users(id) not null,
start_time timestamp not null, -- start time of interview
end_time timestamp not null, -- end time of interview
is_booked bool not null default 'f', -- slot is booked by any candidate or not
created_on timestamp,
constraint unique_interview_slot
exclude using gist (interviewer with =,
tsrange(date_trunc('minute', start_time), date_trunc('minute', end_time), '[]') with &&)
);
This prevents rows with overlapping start/end ranges for the same interviewer. The timestamps are "rounded" to the full minute. You need the extension btree_gist in order to create that constraint.
You can use an UNIQUE INDEX to make this check for you and truncate the timestamp to minutes:
CREATE UNIQUE INDEX idx_interview_slot_ts
ON interview_slot (interviewer, date_trunc('minutes',start_time));
Demo: db<>fiddle

Subtract two timestamptz values and insert the result into a third column

I have the following table:
CREATE TABLE duration
(
departure_time TIMESTAMPTZ,
arrival_time TIMESTAMPTZ,
duration TIME NOT NULL, -- Not sure about the datatype..
flight_id INT UNIQUE NOT NULL,
CHECK (scheduled_duration > 0),
CHECK (scheduled_arrival_time > scheduled_departure_time),
FOREIGN KEY (flight_id) REFERENCES flight(flight_id),
PRIMARY KEY (scheduled_departure_time, scheduled_arrival_time)
);
I want to calculate arrival_time - departure_time and then insert the result into the column duration. Preferably, the result of the duration subtraction would be 6h 30m. I am new to databases and PostgreSQL and I can't find a way to calculate a subtraction of two timestamps, taking into consideration their timezones at the same time.
Use a generated column
CREATE TABLE duration
(
departure_time TIME WITH TIME ZONE,
arrival_time TIME WITH TIME ZONE,
scheduled_duration INT,
flight_id INT,
duration2 TIME GENERATED ALWAYS AS ("arrival_time"::time - "departure_time"::time) STORED,
CHECK (scheduled_duration > 0),
CHECK (arrival_time > departure_time),
FOREIGN KEY (flight_id) REFERENCES flight(flight_id),
PRIMARY KEY (departure_time, arrival_time)
);
SELECT
EXTRACT(EPOCH FROM '2022-07-07 15:00:00.00000'::TIMESTAMP - '2022-07-07 15:00:00.00000'::TIMESTAMP)

I just want to use time in this colum (novice)

CREATE TABLE Vitals
(
Record_No int NOT NULL PRIMARY KEY,
Patient_ID int,
Date_Taken DATE NOT NULL,
Time_Taken time(7) NOT NULL,
Systolic int,
CHECK (Systolic > Diastolic),
Diastolic int,
Heart_Rate int CHECK (Heart_Rate > 30),
CONSTRAINT fk_Patient_ID FOREIGN KEY (Patient_ID) REFERENCES Patients(Patient_ID)
);
But, I get an error
Time_Taken time(7) NOT NULL,
*
ERROR at line 6:
ORA-00907: missing right parenthesis
When I use timestamp default systimestamp
it works. All I need is the time for Time_Taken column.
enter image description here
You can not use the TIME data type as it is not the oracle defined datatype.
You can use the DATE or TIMESTAMP data type to store time with date.
Supported data types in oracle are documented here.

SQL DDL - 2 CHECK Constraints on 1 Attribute

Below is DDL for the table I want to create. However, I want the attribute 'Appointment_datetime' to be a future date and during working hours (between 8:00AM and 5:00PM). I can get the future date part with -'CHECK (Appointment_datetime >= GETDATE()) But how do I get between 8AM and 5PM ontop of this constraint?
CREATE TABLE tAppointment
(
Appointment_ID int NOT NULL PRIMARY KEY,
Appointment_datetime datetime NOT NULL, -- CHECK CONSTRAINTS NEEDED
Appointment_week int NOT NULL,
Appointment_room varchar(5) NOT NULL,
Vet_ID int NOT NULL REFERENCES tVet(Vet_ID),
Owner_ID int NOT NULL REFERENCES tOwner(Owner_ID),
Pet_ID int NOT NULL REFERENCES tPet(Pet_ID)
)
You can just add it in. Here is a method using the hour:
CHECK (Appointment_datetime >= GETDATE() AND
DATEPART(HOUR, GETDATE()) NOT BETWEEN 8 AND 16
)
Note: If you want to take weekends and holidays into account, that is more difficult and probably requires a user-defined function.

ORA-00984 Column not allowed here with date in oracle SQL

Im inserting values into this table
CREATE TABLE Flight (
FlightNumber char(7) primary key,
ArrivalAirportCode char(6) references Airport (Airport_code),
DepartureAirportCode char(6) references Airport (Airport_code),
AircraftNumber varchar2(25) references Aircraft (AircraftNumber),
ArrivalDate date,
ArrivalTime Varchar2(5),
DepartureDate date,
DepartureTime varchar2(5)
);
and here are the values Im inserting into it
INSERT INTO FLIGHT values
('CA3048',
'LHR',
'EDI',
'N859E',
'14-NOV-2014',
'22:15',
'14-NOV-2014',
'20:15');
And I get the column not allowed here error for the 2nd date I insert, but not the first one. I've tried putting quotes around the date but I just get another error.
'14-NOV-2014'
Why are you inserting a string in a DATE column? '14-NOV-2014' is a STRING and NOT a DATE. You should not depend on implicit data type conversion.
Always, convert the string into a DATE explicitly using TO_DATE and proper format mask.
For example,
TO_DATE('14-NOV-2014','DD-MON-YYYY')
One more thing,
DepartureTime varchar2(5)
Makes no sense. You already have a DATE column, a DATE would have the time element too.
No need of a separate time column. A DATE has both date and time elements stored in 7 bytes.
Oracle stores DATE in total of 7 bytes. Each byte in it stores values for an element of the DATE as follows:
Byte Description
---- ------------------------------------------------
1 Century value but before storing it add 100 to it
2 Year and 100 is added to it before storing
3 Month
4 Day of the month
5 Hours but add 1 before storing it
6 Minutes but add 1 before storing it
7 Seconds but add 1 before storing it
All you need to do is just have 2 DATE columns:
CREATE TABLE Flight (
FlightNumber char(7) primary key,
ArrivalAirportCode char(6) references Airport (Airport_code),
DepartureAirportCode char(6) references Airport (Airport_code),
AircraftNumber varchar2(25) references Aircraft (AircraftNumber),
ArrivalDate date,
DepartureDate date
);
And then insert the values as:
INSERT INTO FLIGHT values
('CA3048',
'LHR',
'EDI',
'N859E',
TO_DATE('14-NOV-2014 22:15:00','DD-MON-YYYY HH24:MI:SS'),
TO_DATE('14-NOV-2014 20:15:00','DD-MON-YYYY HH24:MI:SS')
);
Update
As mentioned in the comments by #GriffeyDog and #a_horse_with_no_name.
Alternatively, you could also the ANSI literal instead, for example:
timestamp '2014-11-14 22:15'