How to update the date for a specific ID in Oracle SQL? - sql

I'm setting up a database for a scuba diving company and have a SQL table with values for Student ID (SID), Instructor ID (IID), Item Borrowed (ITEMID), Equipment Borrow Date (BorrowDate), and Equipment Return Date (ReturnDate). How do I change the Equipment Return Date for one of the students? I'd like to add an extra 2 days to the ReturnDate. I created the Borrows table like this:
CREATE TABLE BORROWS(
SID CHAR(15),
ITEMID CHAR(15),
IID CHAR(15),
BORROW_DATE DATE,
RETURN_DATE DATE,
PRIMARY KEY(SID, ITEMID),
FOREIGN KEY(SID) REFERENCES STUDENT(SID) ON DELETE CASCADE,
FOREIGN KEY(ITEMID) REFERENCES EQUIPMENT(ITEMID) ON DELETE CASCADE,
FOREIGN KEY(IID) REFERENCES INSTRUCTOR(SSN) ON DELETE CASCADE
);
I tried doing this in my SQL file:
SELECT SID, ADD_DATE(RETURN_DATE, INTERVAL 2 DAY)
FROM BORROWS
WHERE SID = '005' AND IID = '108';
I'm getting this error back:
SELECT SID, ADD_DATE(RETURN_DATE, INTERVAL 2 DAY)
*
ERROR at line 1:
ORA-00907: missing right parenthesis
Can't figure out where the error is in my code...

Adding two days to a date is as simple as + 2.
select return_date + 2
from borrows
where sid='005'
and iid='108'
The syntax you are looking for might be:
select (return_date + INTERVAL '2' DAY)
from borrows
where sid='005'
and iid='108'

Related

SQL - cannot add or update a child row: a foreign key constraint fails

I keep getting the error:
Cannot add or update a child row: a foreign key constraint fails
(myWork.Bookingss, CONSTRAINT Bookingss_ibfk_1 FOREIGN KEY
(CustomersID) REFERENCES Customers (CustomersID))
I have spent a while researching as this is apart of a school assignment and can not seem to resolve the problem.
Here is my SQL code:
USE myWork ;
DROP TABLE IF EXISTS Bookingss ;
DROP TABLE IF EXISTS Customers ;
CREATE TABLE myWork.Customers
(
CustomersID INT NOT NULL AUTO_INCREMENT,
Surname CHAR(30) NOT NULL ,
FirstName CHAR(30) NOT NULL ,
Title CHAR(10),
DOB DATE,
HouseNumber INT,
StreetName CHAR(30),
Town CHAR(30),
PostCode CHAR(9),
Telephone INT,
PRIMARY KEY (CustomersID)
) ;
CREATE TABLE myWork.Bookingss
(
BookingsID INT NOT NULL AUTO_INCREMENT,
CustomersID INT NOT NULL,
AdultsBooked INT NOT NULL,
ChildrenBooked INT NOT NULL,
Check_In DATE,
Check_Out DATE,
PRIMARY KEY (BookingsID),
FOREIGN KEY (CustomersID)
REFERENCES myWork.Customers (CustomersID)
) ;
SHOW TABLES ;
INSERT INTO myWork.Bookingss ( CustomersID, AdultsBooked , ChildrenBooked , Check_In , Check_Out )
VALUES ("1", "2", "3", "2022-04-10", "2022-04-13" ) ;
INSERT INTO myWork.Customers ( Surname , FirstName , Title , DOB )
VALUES ( "smith" , "ryan" , "Mr" , "1998-02-16" ) ;
SELECT * FROM Customers , Bookingss;
You got the order wrong and some challenges to overcome. You are trying to insert a booking first, and this with an id for a customer that does not yet exist in the customer table at that moment.
You have to insert the customer first, then use the customer's id to insert the booking for the customer (using his id).
And there is the first challenge. The customer id is an auto increment field. You would not know the id when you insert a customer in the table.
You would have to fetch the customer and use the id of that customer to insert a booking for the customer. How do you fetch the customer? Selecting the customer with a specific name surname and first name is not a correct choice, any other field (or composition of fields) that I see in the table definition is not a good choice neither.
You'd need to think further about a good solution. There are several options I could tell you about. But the appropriate solution depends on your assignment/context.
By the way, the last select clause may not deliver the result you expect. You are producing a cartesian product (every row of the first table with every row of the second table). What you probably want is a JOIN where you link the first table with the second table accordingly (e.g. using the primary key and the foreign key).

How do I validate these columns, do i need more complex triggers?

I'm trying to validate the columns in the table ProjectDetails.TimeCards
create table ProjectDetails.TimeCards(
Time_Card_ID int identity (55,15),
Employee_ID int foreign key references HumanResources.Employees(Employee_ID),
Date_Issued date, --DateIssued should be greater than the current date and the project start date (Project start date is from another table).
Days_Worked int constraint chk_Days_Worked check(Days_Worked > '0'),
Project_ID int foreign key references ProjectDetails.Projects(Project_ID),
Billable_hours int constraint chk_Billable_Hours check (Billable_Hours > '0'),
Total_Cost money, -- should be automatically calculated by using the following formula: TotalCost=Billable Hours * BillingRate (billing rate is from another table)
Work_Code_ID int foreign key references ProjectDetails.WorkCodes(Work_Code_ID)
);
I tried building a trigger, but was only able to get the trigger to fire if the Date_Issued was less than the current date
CREATE TRIGGER dateissued
ON ProjectDetails.TimeCards
FOR INSERT
AS
DECLARE #ModifiedDate date
SELECT #ModifiedDate = Date_Issued FROM Inserted
IF (#ModifiedDate < getdate())
BEGIN
PRINT 'The modified date should be the current date. Hence, cannot insert.'
ROLLBACK TRANSACTION -- transaction is to be rolled back
END
i need the trigger to fire if the Date issued is less than the current date and also if date issued is less than the start_date. As for the billing rate calculation i'm lost there.
This is the other table
create table ProjectDetails.Projects(
Project_ID int identity (0100, 01) primary key, -- Primary key
Project_Name char (50) not null,
Start_Date date not null, -- the start date i'm referring to
End_Date date not null,
constraint CheckEndLaterThanStart check (End_Date > Start_Date),
Billing_Estimate money constraint chk_Billing_Estimate check (Billing_Estimate > '1000'),
Client_ID int Foreign Key references CustomerDetails.Clients(Client_ID)
);
I believe this provides the logic you are after. There are a couple of comments in the code for you:
CREATE TRIGGER trg_chk_Date_Issued ON ProjectDetails.TimeCards
FOR INSERT, UPDATE --I assume on need on UPDATE as well, as otherwise this won't validate
AS BEGIN
IF EXISTS(SELECT 1
FROM inserted i
JOIN ProjectDetails.Projects P ON i.Project_ID = P.Project_ID
WHERE i.Date_Issued < CONVERT(date,GETDATE())
OR i.Date_Issued < P.Start_Date) BEGIN
RAISERROR(N'Date Issued cannot be less than the current date or the Project Start Date.', 10,1); --Raised an error, rather than using PRINT
ROLLBACK;
END
END
Note that you may want a different trigger for UPDATE, as if you are updating the row, and Date_Issued has a value lower than the date of the UPDATE, the statement will fail.

How can I get this query to print a record that only exists in one table?

I am trying to create a query that will accept a date from the user and display information from two tables based on this date. This works for all of my tests except my last test. My last test, I enter a date that should return a record that only exists in the expmast table and does not exist in the expbycc table. When I enter the date to try and get this record to be returned, it tells me no records have been found. I know this is because in my where, i have an AND that checks if M.ExpNum = C.ExpNUm which isn;t true for this record because it only exists in one table. I can not figure out how to get this query to work. Any help/advice is greatly appreciated. Below is my script, followed by the table structures used for this query, thank you.
Script:
ACCEPT Date PROMPT 'Enter a date:';
SELECT M.ExpNum, EDate, IsCash, StoreCode, CashAmt, CType, CCNum, Amt
FROM ExpMast M, ExpByCc C
WHERE EDate = to_date('&Date','mm-dd-yy')
AND M.ExpNum = C.ExpNum;
Tables:
CREATE TABLE EXPMAST
(ExpNum NUMBER(2,0) NOT NULL PRIMARY KEY,
EDate DATE,
IsCash VARCHAR2(1),
StoreCode VARCHAR2(4),
CONSTRAINT fk_STORE_EXPMAST FOREIGN KEY (StoreCode)
REFERENCES STORE (Code)
);
CREATE TABLE ExpByCC
(ExpNum NUMBER(2,0) NOT NULL,
CType VARCHAR2(1) NOT NULL,
CCNum VARCHAR2(16) NOT NULL,
Amt DECIMAL(5,2),
CONSTRAINT fk_CRCARD_ExpByCC FOREIGN KEY (CType, CCNum)
REFERENCES CRCARD (CType, CCNum),
CONSTRAINT fk_EXPMAST_ExpByCC FOREIGN KEY (ExpNum)
REFERENCES EXPMAST (ExpNum),
CONSTRAINT pk_ExpByCC PRIMARY KEY (ExpNum, CType, CCNum)
);
You need a left outer join. And you can't express an outer join using your implicit join syntax. You want to use explicit joins in the from clause.
A simple rule: NEVER use commas in the from clause.
Now, it is easy:
SELECT M.ExpNum, EDate, IsCash, StoreCode, CashAmt, CType, CCNum, Amt
FROM ExpMast M LEFT OUTER JOIN
ExpByCc C
ON M.ExpNum = C.ExpNum AND
WHERE M.EDate = to_date('&Date','mm-dd-yy') AND
C.ExpNum IS NULL;

Can't serialize transient record type postgres

I am trying to make my calculation dynamic based on certain criteria as below, but when I try to send the fields dynamically in to my calculation logic, it fails with the error " Can't serialize transient record type":
Create table statement :
create table calculation_t(
Id serial,
product_id integer not null,
metric_id integer not null,
start_date date,
end_date date,
calculation_logic varchar(50),
insert_timestamp timestamp default current_timestamp,
CONSTRAINT calculation_pk PRIMARY KEY(Id),
CONSTRAINT calculation_pid_fk FOREIGN KEY(product_id) REFERENCES Product_T(Product_id),
CONSTRAINT calc_mid_fk FOREIGN KEY(metric_id) REFERENCES metric_T(metric_id)
);
Insert statement :
insert into calculation_t(product_id,metric_id,calculation_logic)
select a.product_id,b.metric_id,
(case when b.metric_id=2 then
('$1-$2') else
'$1/$2' end) calc
from product_t a,metric_t b
Select statement which throws the mentioned error :
select *,(1,2,calculation_logic) from calculation_t
Note : I am using Greenplum database.
Try to remove parenthesis form your query:
select *,1,2,calculation_logic from calculation_t
It worked for me.
Thanx,

What to use: Record or Cursor?

Create a PL/SQL block to retrieve and display data for all pledges made in a specified month. One row of output should be displayed for each pledge. Include the following in each row of output:
• Pledge ID, donor ID, and pledge amount
• If the pledge is being paid in a lump sum, display “Lump Sum”.
• If the pledge is being paid in a monthly payments, display “Monthly - #” (with the # representing the number of months for payment)
• The list should be sorted to display all lump sum pledges first.
here is the table struc.
CREATE TABLE DD_Pledge (
idPledge number(5),
idDonor number(4),
Pledgedate DATE,
Pledgeamt number(8,2),
idProj number(5),
idStatus number(2),
Writeoff number(8,2),
paymonths number(3),
Campaign number(4),
Firstpledge char(1),
CONSTRAINT pledge_id_pk PRIMARY KEY(idPledge),
CONSTRAINT pledge_idDonor_fk FOREIGN KEY (idDonor)
REFERENCES dd_donor (idDonor),
CONSTRAINT pledge_idProj_fk FOREIGN KEY (idProj)
REFERENCES dd_project (idProj),
CONSTRAINT pledge_idStatus_fk FOREIGN KEY (idStatus)
REFERENCES dd_status (idStatus));
I tried to use record but seems that record is not going to work as it gives me error when the specified month has more then one pledge. Is there a way to do it using record (coz this is and assignment we take it after we covered the record)
Maybe cursor will be a good choice but due to the point mentioned earlier I'd like to know what are the ways to solve this one.
SELECT
p.idPledge,
p.idDonor,
p.Pledgeamt as this_payment,
case
when p.paymonths = 0 then 'Lump Sum'
else 'Monthly - ' || p.paymonths
end as payment_method
FROM
dd_pledge p
WHERE
TRUNC(p.Pledgedate) >= '01-Mar-2010' AND TRUNC(p.Pledgedate) < '01-Apr-2010'
order by
4
Assuming you'll add your month's start/end dates as required.