I am using Oracle SQL.
Here is the table rental, and the CC_Type column means the credit card type. After creating the table, I want to add a constraint to make sure the credit card is either 'credit' or 'debit'
CREATE TABLE rental
( Rental_Num VARCHAR2(5) CONSTRAINT rental_PK PRIMARY KEY,
Rent_Date DATE DEFAULT SYSDATE,
Credit_Card_Num CHAR(16),
CC_Type CHAR(7),
Member_ID VARCHAR2(5)
);
Therefore, I try to write:
ALTER TABLE RENTAL
2 ADD CONSTRAINT CC_TYPE_CK
3 CHECK(CC_TYPE LIKE 'Credit' OR CC_TYPE LIKE 'Debit');
But SQL yield: cannot validate (SYSTEM.CC_TYPE_CK) - check constraint violated
I don't understand it violated what? And how to fix it?
Thanks!!
You apparently have data in the table that violates the constraint. Your code basically works; here is a db<>fiddle (this fixes the extra comma before the closing paren in the create table statement).
So, look for the bad data:
select r.*
from rental r
where r.cc_type not in ('Credit', 'Debit');
I would also write the constraint using in . . . it is simpler:
ALTER TABLE RENTAL
ADD CONSTRAINT CC_TYPE_CK
CHECK (CC_TYPE IN ('Credit', 'Debit'));
just remove , after Member_ID VARCHAR2(5) other wise your query working fine
CREATE TABLE rental
( Rental_Num VARCHAR2(5) CONSTRAINT rental_PK PRIMARY KEY,
Rent_Date DATE DEFAULT SYSDATE,
Credit_Card_Num CHAR(16),
CC_Type CHAR(7),
Member_ID VARCHAR2(5)
);
ALTER TABLE RENTAL
ADD CONSTRAINT CC_TYPE_CK
CHECK(CC_TYPE LIKE 'Credit' OR CC_TYPE LIKE 'Debit');
demo link
I agree with Gordon Linoff, Check for the data in cc_type.
select Distinct r.cc_type
from rental r;
If you still want to create the constraint even when you have the other CC_TYPEs(in the other words, without validating the existing data) then try this
ALTER TABLE RENTAL
ADD CONSTRAINT CC_TYPE_CK
CHECK (CC_TYPE IN ('Credit', 'Debit')) NOVALIDATE;
Related
Please, help!
I have trigger:
CREATE TRIGGER check_reservation BEFORE INSERT ON order
FOR EACH ROW
DECLARE mistake INTEGER;
BEGIN
SELECT count(*) INTO mistake FROM order join reserving
on id_order = reserving.order_id_order
WHERE reserving.room_num_room=:new.room_num_room
AND (order.reservation_from < :new.reservation_from AND :new.reservation_from < order.reservation_to) OR
(order.reservation_from < :new.reservation_from AND :new.reservation_to < order.reservation_to) OR
(:new.reservation_from <= order.reservation_from AND order.reservation_to <= :new.reservation_to);
IF mistake>0 THEN
raise_application_error(-20001,'reservation already exists');
END IF;
END;
The idea of the trigger is not to allow make a reservation on already booked room. When I run it I had check compiler log error message. How can I change trigger?
I have following tables:
CREATE TABLE order (
id_order CHAR(100) NOT NULL,
reservation_from DATE NOT NULL,
reservation_to DATE NOT NULL,
);
ALTER TABLE order ADD CONSTRAINT order_pk PRIMARY KEY ( id_order );
CREATE TABLE room (
num_room CHAR(100) NOT NULL,
type VARCHAR2(100) NOT NULL,
);
ALTER TABLE room ADD CONSTRAINT room_pk PRIMARY KEY ( num_room );
CREATE TABLE reserving (
room_num_room CHAR(100) NOT NULL,
order_id_order CHAR(100) NOT NULL
);
ALTER TABLE reserving ADD CONSTRAINT reserving_pk PRIMARY KEY ( room_num_room,
order_id_order );
ALTER TABLE reserving
ADD CONSTRAINT reserving_order_fk FOREIGN KEY ( order_id_order )
REFERENCES order ( id_order );
ALTER TABLE reserving
ADD CONSTRAINT reserving_room_fk FOREIGN KEY ( room_num_room )
REFERENCES room ( num_room );
I tried recreating the trigger with the statements above. The statements failed with several errors, it looks as if they were not tested before posting them as question. Please take some time posting a quality question.
Example:
CREATE TABLE room (
num_room CHAR(100) NOT NULL,
type VARCHAR2(100) NOT NULL, << this trailing comma makes this statement fail.
);
After fixing all errors I ran the "CREATE TRIGGER" and it errored out with
PLS-00049: bad bind variable 'NEW.ROOM_NUM_ROOM'
That is because the column ROOM_NUM_ROOM does not exist in the "ORDER" table.
If I remove the reference to 'NEW.ROOM_NUM_ROOM' the trigger compiles successfully.
However, as gsalem pointed out, this will not work because it will raise a mutating table error. In the trigger code you cannot execute DML referencing the table that the trigger is on. There is plenty of documentation on how to avoid mutating table errors.
I'm new to learning SQL. When I create this table, it has an Asterix (*) under the first parenthesis of the "(dbClassID)" and says "missing right parenthesis"
Does anyone know why it does that and how I can fix it?
CREATE TABLE vod_classification (
dbClassId CHAR(4) NOT NULL,
dbDescription VARCHAR2(100)
CONSTRAINT vod_classification_PK PRIMARY KEY (dbClassId)
);
CONSTRAINT is part of table creation and need to be comma delimited as other column:
CREATE TABLE zz_classification (
dbClassId CHAR(4) NOT NULL,
dbDescription VARCHAR2(100),
CONSTRAINT vod_classification_PK PRIMARY KEY( dbClassId)
);
Tables contain columns and constraints
you are missing , here try this VARCHAR2(100),
For a single-column constraint, it's neater to define it inline as part of the column:
create table vod_classification
( dbclassid varchar2(4) not null constraint vod_classification_pk primary key
, dbdescription varchar2(100) not null constraint vod_classification_uk unique
);
I have corrected the CHAR column to the standard string type which is VARCHAR2 in Oracle.
(PK columns will be not null automatically, but I've left it in for completeness and in case you later create table as select.)
When using the "Create" code, you must use a comma in the line where you define each column of the table. Except the last column. You can read the oracle sql syntax link as follows: https://docs.oracle.com/cd/E11882_01/server.112/e41085/sqlqr01001.htm#SQLQR110
I am trying to make a procedure that takes makes potential empty "received" fields use the current date. I made a sequence called Order_number_seq that populates the order number (Ono) column. I don't know how to link errors in the orders table to a entry in the Orders_errors table.
this is what i have so far:
CREATE PROCEDURE Add_Order
AS BEGIN
UPDATE Orders
CREATE Sequence Order_number_seq
Start with 1,
Increment by 1;
UPDATE Orders SET received = GETDATE WHERE received = null;
These are the tables I am working with:
Orders table
(
Ono Number Not Null,
Cno Number Not Null,
Eno Number Not Null,
Received Date Null,
Shipped_Date Date Null,
Creation_Date Date Not Null,
Created_By VARCHAR2(10) Not Null,
Last_Update_Date Date Not Null,
Last_Updated_By VARCHAR2(10) Not Null,
CONSTRAINT Ono_PK PRIMARY KEY (Ono),
CONSTRAINT Cno_FK FOREIGN KEY (Cno)
REFERENCES Customers_Proj2 (Cno)
);
and
Order_Errors table
(
Ono Number Not Null,
Transaction_Date Date Not Null,
Message VARCHAR(100) Not Null
);
Any help is appreciated, especially on linking the orders table errors to create a new entry in OrderErrors table.
Thanks in advance.
Contrary to Martin Drautzburg's answer, there is no foreign key for the order number on the Order_Errors table. There is an Ono column which appears to serve that purpose, but it is not a foreign as far as Oracle is concerned. To make it a foreign key, you need to add a constraint much like the Cno_FK on Orders. An example:
CREATE TABLE Order_Errors
(
Ono Number Not Null,
Transaction_Date Date Not Null,
Message VARCHAR(100) Not Null,
CONSTRAINT Order_Errors_Orders_FK FOREIGN KEY (Ono) REFERENCES Orders (Ono)
);
Or, if your Order_Errors table already exists and you don't want to drop it, you can use an ALTER TABLE statement:
ALTER TABLE Order_Errors
ADD CONSTRAINT Order_Errors_Orders_FK FOREIGN KEY (Ono) REFERENCES Orders (Ono)
;
As for the procedure, I'm inclined to say what you're trying to do does not lend itself well to a PROCEDURE. If your intention is that you want the row to use default values when inserted, a trigger is better suited for this purpose. (There is some performance hit to using a trigger, so that's a consideration.)
-- Create sequence to be used
CREATE SEQUENCE Order_Number_Sequence
START WITH 1
INCREMENT BY 1
/
-- Create trigger for insert
CREATE TRIGGER Orders_Insert_Trigger
BEFORE INSERT ON Orders
FOR EACH ROW
DECLARE
BEGIN
IF :NEW.Ono IS NULL
THEN
SELECT Order_Number_Sequence.NEXTVAL INTO :NEW.Ono FROM DUAL;
END IF;
IF :NEW.Received IS NULL
THEN
SELECT CURRENT_DATE INTO :NEW.O_Received FROM DUAL;
END IF;
END;
/
This trigger will then be executed on every single row inserted into the Orders table. It checks if the Ono column was NULL and replaces it with an ID from the sequence if so. (Be careful that you don't ever provide an ID that will later be generated by the sequence; it will get a primary key conflict error.) It then checks if the received date is NULL and sets it to the current date, using the CURRENT_DATE function (which I believe was one of the things you were trying to figure out), if so.
(Side note: Other databases may not require a trigger to do this and instead could use a default value. I believe PostgreSQL, for instance, allows the use of function calls in its DEFAULT clauses, and that is how its SERIAL auto-increment type is implemented.)
If you are merely trying to update existing data, I would think the UPDATE statements by themselves would suffice. Is there a reason this needs to be a PROCEDURE?
One other note. Order_Errors has no primary key. You probably want to have an auto-incrementating surrogate key column, or at least create an index on its Ono column if you only ever intend to select off that column.
There are a number of confusing things in your question:
(1) You are creating a sequence inside a procedure. Does this even compile?
(2) Your procedure does not have any parameters. It just updates the RECEIVED column of all rows.
(3) You are not telling us what you want in the MESSAGE column.
My impression is that you should first go "back to the books" before you ask questions here.
As for your original question
how to link errors in the orders table to a entry in the Orders_errors
table.
This is aleady (correctly) done. The Orders_error table contains an ONO foreign key which points to an order.
On creating table i needed to add a check statement for current date should be created date cell. So for example
create table own_departments
(
id number(4) primary key,
name varchar2(30),
num_of_emps number(4) default '0',
est_date date,
check(est_date < sysdate)
);
This check gives errors.
Is anyone know how to check DATE format???
If you are using SQL Server then you will need to create a table constraint...
ALTER TABLE _departments WITH CHECK ADD CONSTRAINT CK_DateGreaterThan CHECK (([est_date]>YOUR_DATE))
GO
ALTER TABLE _departments CHECK CONSTRAINT CK_DateGreaterThan
GO
If you're using SQL Server / Oracle / MS Access, then it should be something like this:
create table own_departments
(
id number(4) primary key,
name varchar2(30),
num_of_emps number(4) default '0',
**est_date date check(est_date < sysdate)**
);
I am encountering a problem for my database.
And tried to do the query for how many transactions have movie "Harry_Potter"?
so I used SQL query:
SELECT
COUNT(td.movie) AS number_of_occurrence,
td.transaction_number
FROM
TransactionDetails td,
MovieDetails md
WHERE
md.movie = Harry_Potter
But it asks for Harry_Potter enter parameter value why?
The relevant SQL statements are
CREATE TABLE TransactionDetails
(
transaction_number INTEGER PRIMARY KEY,
movie VARCHAR(30) NOT NULL,
date_of_transaction DATE NOT NULL,
member_number INTEGER NOT NULL
)
CREATE TABLE MovieDetails
(
movie VARCHAR(30) PRIMARY KEY,
movie_type VARCHAR(3) NOT NULL,
movie_genre VARCHAR(10) NOT NULL
)
ALTER TABLE TransactionDetails
ADD CONSTRAINT member_number_fk FOREIGN KEY (member_number) REFERENCES LimelightMemberDetails(member_number);
ALTER TABLE TransactionDetails
ADD CONSTRAINT transaction_number_drink_fk FOREIGN KEY (transaction_number) REFERENCES DrinkTransactionDetails(transaction_number);
ALTER TABLE TransactionDetails
ADD CONSTRAINT transaction_number_food_fk FOREIGN KEY (transaction_number) REFERENCES FoodTransactionDetails(transaction_number);
ALTER TABLE TransactionDetails
ADD CONSTRAINT movie_fk FOREIGN KEY (movie) REFERENCES MovieDetails (movie);
Thank you for your help! If there is anything wrong with my database design please let me know! thank you!
Change the query to something like
SELECT
COUNT(td.movie) AS number_of_occurrence,
td.transaction_number
FROM
TransactionDetails td,
MovieDetails md
WHERE
md.movie = "Harry_Potter"
Seeing as movie is a string, you need quotes around the value you are looking for.
If I am not mistaken MS Access takes " and SQL SERVER takes '
try this
md.movie = "Harry_Potter"
I guess, you are simply missing the quotation marks around the string you are comparing.