Oracle Check Constraint Issue with to_date - sql

So I'm new to Oracle, trying to create a table as follows:
create table Movies (
Title varchar2 primary key,
Rating NUMBER CONSTRAINT Rating_CHK CHECK (Rating BETWEEN 0 AND 10),
Length NUMBER CONSTRAINT Length_CHK CHECK (Length > 0),
ReleaseDate DATE CONSTRAINT RDATE_CHK
CHECK (ReleaseDate > to_date('1/1/1900', 'DD/Month/YYYY')),
CONSTRAINT title_pk PRIMARY KEY (Title)
)
Per my assignment, the ReleaseDate must have a constraint enforcing only dates after 1/1/1900. The input my professor has given us for dates is as follows: 13 August 2010
Can one of you experts see where my issue lies?

The spec for Title column is incorrect, as well as the date string/format model combination in your to_date function call. Specify a column length for TITLE, and fix the date string to match the format model.
Try this:
create table Movies (
Title varchar2(100),
Rating NUMBER CONSTRAINT Rating_CHK CHECK (Rating BETWEEN 0 AND 10),
Length NUMBER CONSTRAINT Length_CHK CHECK (Length > 0),
ReleaseDate date CONSTRAINT RDATE_CHK CHECK (ReleaseDate > to_date('1/January/1900', 'DD/Month/YYYY')),
CONSTRAINT title_pk PRIMARY KEY (Title)
)
Update:
As an aside, Title is a lousy primary key. Ever hear of two different movies with the same title? Can you say "remake"?
Another edit. I guess since your prof gave you the date format, you should make the date string match the format model. I've updated my answer.

I think 'Month' in TO_DATE is looking for a month name - not a number.
Either change the second 1 to January or change Month to MM.

Related

How to limit a date constraint to only allow a user to enter dates that fall on a specific day of the week in Oracle SQL

I've been stuck with this problem for a few days now and I've been through many different questions that i've found via google/stack overflow but I've been unable to solve it.
I need to create a table that allows a user to enter a date for an appointment, one of the constraints is that the date that is entered can only be a date that is a monday or a friday.
Here are several of my attempts, some worked in that they allow me to create the table, but then when it comes to entering data, it says invalid month, invalid datatype or a plethora of other errors. (I've also removed other columns from the below code just because they're not relevant to the question).
CREATE TABLE t_appointments
(appointment_id NUMBER(10,0) CONSTRAINT appointments_appoint_id_pk PRIMARY KEY,
appoint_date DATE CONSTRAINT appointments_app_date_nn NOT NULL
CONSTRAINT appointments_app_date_ck CHECK (to_char(appoint_date,'Day') IN ('Monday','Friday'));
I also tried
CREATE TABLE t_appointments
(appointment_id NUMBER(10,0) CONSTRAINT appointments_appoint_id_pk PRIMARY KEY,
appoint_date DATE CONSTRAINT appointments_app_date_nn NOT NULL
CONSTRAINT appointments_app_date_ck CHECK (to_char(to_date(appoint_date,'DD-MM-YYYY'),'Day') IN ('Monday','Friday'));
Any help would be greatly appreciated, thank you.
This is the issue in Oracle:
Name of day, padded with blanks to display width of the widest name of day in the date language used for this element.
So, try this:
CONSTRAINT appointments_app_date_ck CHECK (to_char(appoint_date, 'Day') IN ('Monday ', 'Friday '))
Or, you can do:
CONSTRAINT appointments_app_date_ck CHECK (to_char(appoint_date, 'D') IN ('2', '6'))

Why Postgresql doesn't allow grouping sets in INSERT SELECT queries?

The issue here is simple as that, Postgresql doesn't allow the following query structure:
-- TABLE OF FACTS
CREATE TABLE facts_table (
id integer NOT NULL,
description CHARACTER VARYING(50),
amount NUMERIC(12,2) DEFAULT 0,
quantity INTEGER,
detail_1 CHARACTER VARYING(50),
detail_2 CHARACTER VARYING(50),
detail_3 CHARACTER VARYING(50),
time TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT LOCALTIMESTAMP(0)
);
ALTER TABLE facts_table ADD PRIMARY KEY(id);
-- SUMMARIZED TABLE
CREATE TABLE table_cube (
id INTEGER,
description CHARACTER VARYING(50),
amount NUMERIC(12,2) DEFAULT 0,
quantity INTEGER,
time TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT LOCALTIMESTAMP(0)
);
ALTER TABLE table_cube ADD PRIMARY KEY(id);
INSERT INTO table_cube(id, description, amount, quantity, time)
SELECT
id,
description,
SUM(amount) AS amount,
SUM(quantity) AS quantity,
time
FROM facts_table
GROUP BY CUBE(id, description, time);
----------------------------------------------------------------
ERROR: grouping sets are not allowed in INSERT SELECT queries.
I think it's pretty obvious that CUBE produces null results on every field indicated as a grouping set (as it computes every possible combination), therefore I can not insert that row in my table_cube table, so , does Postgres just assume, that I'm trying to insert a row in a table with a PK field? Even if the table_cube table doesn't have a PK, this cannot be accomplished.
Thanks.
Version: PostgreSQL 9.6
You have define table_cube(id) as Primary Key. So, If Cube contains null
values, it can't be inserted. I have checked without having id as Primary
Key, It works fine and when define id as primary key I got error:
"ERROR:id contains null values" SQL state: 23502
As suggested by Haleemur Ali,
"If a constraint is required, use a unique index with all the grouping
set columns: CREATE UNIQUE INDEX unq_table_cube_id_description_time ON
table_cube(id, description, time); Please update your question with more
information on database & version."
is a good option. But you have to remove Primary Key On "Id" and assign only Unique Key as suggested above as with having primary key and unique key again get this error:
ERROR: null value in column "id" violates not-null constraint
DETAIL: Failing row contains (null, null, 1300, 1522, null).
SQL state: 23502
So, the conclusion is, with unique index there is no need of Primary Key or with cube there is no need of unique index or Primary Key.

SQL Create Table Default value as specific date

I'm using Oracle's APEX and trying to set the default date of one of my columns to '31-dec-2013', but for the life of me, it's not happening. I've tried many syntax variations and gotten a number of errors such as "not a valid month" and "such a unique or primary key exists" something to that effect. Please help! here's my code:
Create Table Lease(
LeaseNo number(8) not null unique,
PropertyID number(6) not null,
ClientId varchar2(4) not null,
Leasestartdate date not null,
LeaseEndDate date dEFAULT ('31-12-2013'),
MonthlyRent number(8,2) check (MonthlyRent >1000),
Primary Key (LeaseNo),
Foreign key (propertyId) references property(Propertyid),
Foreign key (clientId) references client(clientid));
It threw the "not a valid month" error.
You can use to_date with an explicit date format model as ThorstenKettner shows, which means you won't be relying on the session's NLS_DATE_FORMAT. You can also use a date literal, which is always in YYYY-MM-DD format:
...
LeaseEndDate date default date '2013-12-31',
...
Largely a matter of personal preference between the two though; I happen to prefer this, partly because it's slightly less typing, but also because there is no possibility of ambiguity between DD-MM and MM-DD.
Use TO_DATE to convert a string to date:
...
LeaseEndDate date default to_date('31-12-2013','dd-mm-yyyy')
...
Here are 2 Corrections
First remove UNIQUE clause from LeaseNo, you cant make a cols primary key that has the unique Constraint already.
And, try this Format in default clause - '31-DEC-2013'

Creating a table with an age constraint based on a date_of_birth attribute with PostgreSQL

CREATE TABLE customer (
date_of_birth date NOT NULL
);
Trying to make it so that someone cannot enter an age less than 18 when inserting values into the table. How would I do this with the date_of_birth attribute?
Note: I do know how to use the CHECK(age > 18), but I don't know how to incorporate this with the date_of_birth attribute.
Use a CHECK constraint based on the value of current_date. Since current_date always increases over time, any value that passes this constraint today will also pass it tomorrow.
CREATE TABLE customer (
date_of_birth date NOT NULL
check ( date_of_birth < (current_date - interval '18' year ) )
);
insert into customer values ('1996-09-29');
ERROR: new row for relation "customer" violates check constraint "customer_date_of_birth_check"
insert into customer values ('1996-09-28');
Query returned successfully: one row affected, 22 ms execution time.

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.