SQL query -> normal english - sql

Can someone please help me put this query in to normal English. No technical terms needed.
This is a past paper question from an exam and it says "Explain in English what the following fragment of code does" Thanks.
CREATE TRIGGER SimpleTrigger
AFTER UPDATE OF Quantity ON Stock
FOR EACH ROW
WHEN (:new.Quantity < 10)
BEGIN
INSERT INTO Reorder(StockCode, StockName, Quantity)
VALUES (StockCode, StockName, 100);
END;

Whenever an update is applied to the column Quantity in the table Stock and the
new value of Quantity is less than 10, I want to insert a new row into the table Reorder.
To set the values for the new row in Reorder copy the values from the columns StockCode and StockName, for the updated row, to their corresponding columns and set the value of Quantity to be 100.
If you are studying for an exam, I suggest you phrase questions
does code XYZ mean Blah Blah Blah.
It will stick better.

Related

What would be the possible outcome of this table in oracle?

I have a "Products" table that has two columns: product_code and product_name. The table is empty
and I want to execuite the following SQL statement.
INSERT INTO Products VALUES (100,’PIZZA’);
INSERT INTO Products VALUES (150,’PASTA’);
UPDATE Products SET product_name = ’PAPAYA’
WHERE product_code = 100;
CREATE PROFILE prof_sales LIMIT
IDLE_TIME 15;
UPDATE Products SET product_name = ’POTATO’
WHERE product_code = 150;
ROLLBACK;
Does the table remain empty because of the ROLLBACK?
The table Products will have two records. 100 PAPAYA and 150 PASTA.
Or the table Products will have two records. 100 PIZZA and 150 PASTA.
The table Products will have two records. 100 PAPAYA and 150 POTATO.
The PROFILE prof_sales will not be created.
These are the assumptions I am making and need an explanation for each assumption
as I am learning. Sorry I couldn't check the answers as my oracle 18c crashed for some reason.
It would be very kind if there is anyone who can help.
None of the above.
The table will be empty but not because of the rollback.
All the INSERT and UPDATE statements will fail with the exception:
ORA-01756: quoted string not properly terminated
Because you are using the character ’ for string literals when it should be '.
db<>fiddle here
If you fix the statements so they are all valid SQL statements then a DDL statement will implicitly COMMIT the prior statements; and then all the statements before the DDL statement will be committed and all the statements afterwards will ROLLBACK.
Since this looks like a homework/exam style exercise I'll leave working out exactly what happens to you.

I have a table where I need to update or insert depending on field paramaters

I have spent many hours researching this problem and trying various solutions but I never quite find a suitable solution for my specific problem. I am new to SQL and some of the examples are confusing as well.
So here is my dilemma. I have a equipment table that tracks oil changes for specific units in a database. The table looks like this:
**id UnitID Posted_On Date_Completed Note OverDueBy**
1 BT-109F 2019-02-04 2019-02-14 Hrs Overdue 23
1 BT-108G 2020-01-17 2020-01-22 Days Overdue 12
1 BT-122K 2020-01-02 2020-01-16 Days Overdue 12
1 BT-109F 2019-02-04 Days Overdue 3
The example records above need to be created or updated by the query. The date completed is entered manually by the technician when he has completed the oil change.
What I want the query to do is, Check to see if a specific Unit has a record where the 'Date_Completed' field is empty, and if so update the 'OverDueBy' field to reflect the new value. If all the records for the specified Unit have the 'Date_Completed' fields filled in, then the query should create a new record will all fields filled in except for the 'Date_Completed' field.
Can anyone help me construct such a query?
Thanks
Clan
First create a unique partial index for the column UnitID:
CREATE UNIQUE INDEX idx_unit ON tablename(UnitID)
WHERE Date_Completed IS NULL;
so that only 1 row with Date_Completed=null is allowed for each UnitID.
So a statement like this:
INSERT INTO tablename(id, UnitID, Posted_On, Date_Completed, Note, OverDueBy)
VALUES (?, 'BT-109F', ?, null, ?, ?)
ON CONFLICT(UnitID) WHERE Date_Completed IS NULL DO UPDATE
SET OverDueBy = ?;
will insert the new values only if there is no row already for UnitID='BT-109F' with null in Date_Completed.
But if there is such a row then it will update the column OverDueBy.
I'm not sure what values you want to insert or what will be the updated value so replace the ? with the appropriate values.
Firstly I would use a view rather than a table to store any calculated data - it reduces storage overheads and will update the calculation every time the view is opened.
If you're using SQLite you should be able to get the overdue by subtracting the Posted_On from its function to return today's date something like date('now') or julianday('now') - read up on and test the functions to ensure it does what you want.
So along the lines of:-
create view MyView as select *, julianday('now') - julianday(Posted_On) as OverDueBy from ClansTable where Date_Completed is null;
If you want to store a snapshot you can always create a table from a view in any case:-
create table MyStoredOverduesOn4thFeb as select * from MyView;
You can find your units that have all Date_Completed and create a single new record like so:-
Create table CompletedUnits as select id, UnitID, max(posted_on) as latest_posted_on, '' as Date_Completed from ClansTable group by id, UnitID having count(*) = count(Date_Complete);
Test this SQL and see if you can get it working - note I've created a text field for the date. Apparently there is no date/datetime data type as such:-
https://www.sqlitetutorial.net/sqlite-date/
Hope this helps,
Phil
I think you need something like this:
MERGE INTO EQUIPMENT A
USING (SELECT * FROM EQUIPMENT B WHERE DATE_COMPLETED IS NULL) C
ON (A.UNITID=C.UNITID)
WHEN MATCHED THEN UPDATE SET A.OVERDUEBY="new value"
WHEN NOT MATCHED THEN INSERT (A.id,A.UnitID,A.Posted_On,A.Date_Completed,A.Note,A.OverDueBy)
VALUES (C.id,C.UnitID,C.Posted_On,NULL,C.Note,C.OverDueBy)
Not sure where new values from update will come from. It's not clear in your question. But something like this could work.

SQL Trigger to allow only customers who are old enough to buy a book?

I have 3 tables, person, audiobook and audiobook_purchases. My database is running MariaDB.
person has fields: id, date_of_birth;
audiobook has fields: ISBN, age_rating, title;
audiobook_purchases has fields: ISBN, customer_id, date_of_purchase;
I'm trying to write a trigger to make sure that when a customer tried to purchases an audiobook, they are old enough to do so according to the age_rating in audiobook.
For example, If Harry Potter and the Philosipher's Stone had age rating 16 and customer Jennifer (ID 1) with date of birth 2010-01-01 tried to purchase this book, this would not be allowed, but Dominick(ID 2) with date_of_birth 1978-01-01 would be allowed.
Please could someone show me a way to run this trigger?
I don't know MariaDB in particular, so my answer may need some adjustments.
You want to create an insert trigger on audiobook_purchase so that a new order will be inserted only if the person who wants to place the order is old enough according to audiobook.age_rating.
First you need to figure out a way of extracting the year from person.date_of_birth. Something like the YEAR() scalar function will probably be available. MariaDB may also provide a NOW() function, which gives the current date. So the person age right now will be: YEAR(NOW()) - YEAR(person.date_of_birth).
Then you have to write the insert trigger. The tricky part is to query the person table to get the person date_of_birth from his id, then to compare it to audiobook.age_rating.
Let's set out an example. First we declare the tables schemas:
CREATE TABLE person(id, name, date_of_birth);
CREATE TABLE audiobook(isbn, age_rating, title);
CREATE TABLE audiobook_purchases(isbn, customer_id, date_of_purchase);
Then we put in some data:
INSERT INTO person VALUES (10, "jennifer", '2010-01-01');
INSERT INTO person VALUES (20, "dominick", '1978-01-01');
INSERT INTO audiobook VALUES (1234, 16, "harry potter");
Then we create the trigger:
CREATE TRIGGER check_purchases
AFTER INSERT ON audiobook_purchases
FOR EACH ROW
WHEN (
SELECT strftime('%Y', 'now') - strftime('%Y', date_of_birth) AS age
FROM person
WHERE new.customer_id=person.id) < (
SELECT audiobook.age_rating
FROM audiobook
WHERE audiobook.isbn=new.isbn)
BEGIN
DELETE FROM audiobook_purchases
WHERE isbn=new.isbn AND
customer_id=new.customer_id AND
date_of_purchase=new.date_of_purchase;
END;
I'll broke down the trigger into smaller steps:
AFTER INSERT ON audiobook_purchases creates a trigger on table audiobook_purchases which will be triggered after the insertion of a new record.
FOR EACH ROW applies the trigger to each new record inserted.
The WHEN clause limits triggering only to those records who satisfy its condition. On the left side of the < sign of the condition there is a query which selects the age of the customer. On the right side there is a query which selects the age rating of the book. Notice the reference to a new table. This table stores the record which triggers the event (see the two examples below). strftime is a scalar function which formats datetime stamps in SQLite. You can read:
strftime('%Y', 'now') as YEAR(NOW()) and
strftime('%Y', date_of_birth) as YEAR(date_of_birth).
Finally between BEGIN and END there are instructions that will be executed on triggering. In this case there is a single instruction which removes the record just inserted. MariaDb may provide a ROLLBACK statement, which can be more efficient than the DELETE statement.
So, for example:
INSERT INTO audiobook_purchases VALUES (1234, 10, '2018-11-25');
will activate the trigger, because the customer with id=10 ('jennifer') is 8 years old and the book with isbn=1234 requires the customer to be at least 16 years old, while:
INSERT INTO audiobook_purchases VALUES (1234, 20, '2018-11-25');
will not activate the trigger, because this customer is 40 years old.
You must be aware that this solution silently ignore the invalid order. I don't know if this is your desired behaviour.
I tested this trigger on SQLite 3.11.0, so it may not be compatible with your SQL interpreter.

Need Help using a loop to perform a mass insert in SQL

First off, i should say up front that i am not a very strong SQL person, so please be gentle :)
I need to perform about 400 inserts into a particular table. The data that i will be using for these inserts, i can collect from a SELECT statement that runs off a different table. I only need the data from 1 column from this table.
So, im hoping someone can help me write the SQL that will basically take the list of id's that are returned from my select, and use that list to do a mass insert into another table.
In psuedocode, something like this:
Select BankID from BankTable; - this returns 300 rows
Insert Into AccountTable -- this will add all 300 rows into the 2nd table
Values
(BankID)
thanks in advance guys...
Very simple, you basically said it. :-)
INSERT Into AccountTable (BankId, SecondColumn) SELECT BankId,'XXX' as staticText FROM BankTable;
It can be done in one statement:
Insert Into AccountTable (bankid)
Select BankID from BankTable
This assumes that the column in AccountTable is also named bankid; if not, just set the name appropriately in the parenthesis.
Keep in mind your INSERT statement must include the columns if the select statement does not match your table definition precisely.
INSERT AccountTable (BankID)
SELECT BankID
FROM BankTable
For multiple columns simply include the column list:
INSERT AccountTable (BankID, BankName)
SELECT BankID, BankName
FROM BankTable
You can also run into type conversion issues if the data types of the columns don't match (i.e. integer fields won't take alpha characters, etc.), but it is not a necessity that the column names match. Just get the order of columns and types right and you should be good.

Insert or Replace with sum of old values

I am building Inventory Application using PhoneGap.In that i have one module STOCK for stock management.
Stock Table Query
CREATE TABLE STOCK (
sto_id INTEGER PRIMARY KEY AUTOINCREMENT,
pro_id INTEGER FOREIGNKEY REFERENCES PRODUCT(pro_id) UNIQUE,
quantity TEXT
)
INSERT OR REPLACE Query
INSERT OR REPLACE INTO STOCK (pro_id,quantity) VALUES ("1","5");
There is not a single issue with this query its working perfectly but i want to update SUM of OLD VALUES WITH NEW ONE.
Example:
pro_id quantity
1 5
This is existing record so now when i will fire above query for new transaction which have 3 quantity then quantity should be (5 (old) + 3 (new) ) = 8.
So after updateing record it looks like.
pro_id quantity
1 8
How can i solve this any idea. or let me know if i am on wrong way.
Thanks.
Actually I am not real founder of this solution. The real hero is Daverandom with the help of him i have solve my issue.
He has suggest me to follow this solution and that is really helpful to find my solution.
Older query looks like as
INSERT OR REPLACE INTO STOCK (pro_id,quantity) VALUES ("1","5");
New Query looks like as
INSERT OR IGNORE INTO STOCK (pro_id,quantity) VALUES (1,0) ;
UPDATE STOCK SET quantity = quantity + 2 WHERE pro_id=1;
Update:
If you will not add WHERE pro_id="val" in UPDATE then it will UPDATE all rows.
So that will generate will appropriate result.
When user fire query first time then quantity will be 2 and when you fire same query second time it will 4.
So, We can change that value in each update.
Again thanks to Daverandom.
In SQLite, you can create a trigger to handle such functionality:
CREATE TRIGGER t1 BEFORE INSERT ON STOCK WHEN NEW.pro_id IN (SELECT pro_id FROM STOCK) BEGIN
UPDATE STOCK SET quantity=COALESCE(NEW.quantity, 0)+COALESCE((SELECT quantity FROM STOCK WHERE pro_id=NEW.pro_id), 0) WHERE pro_id=NEW.pro_id;
SELECT RAISE(IGNORE); -- Ignore INSERT
END;
From now on, whenever you try to insert an existing pro_id, update on quantity is done instead. Conflict clause (OR REPLACE) doesn't matter as trigger will handle it (for pro_id).
Yet another, this time without triggers, using single statement solution:
INSERT OR REPLACE STOCK(pro_id, quantity)
SELECT npro_id, COALESCE(nqty, 0)+COALESCE(quantity,0) FROM (
SELECT 123 AS npro_id, 9999 AS nqty
) LEFT JOIN STOCK ON npro_id=pro_id;
Just replace 123 with new prod_id and 9999 with new quantity.