Column Not Allowed SQL - sql

Error Code Screenshot (ShipDate is now the error)
For my school project we are to create a product database where the customer places an order etc. I've compared my code to classmates and it's the essentially the same except I have less columns. This section of the code inserts the user input into the Orders Table.
The 2nd to last Column, OrderStatus, is where the * appears in the console. I apologize ahead of time if it looks messy, for some reason the format in the Body doesn't carry over to publish posts.
CODE:
INSERT INTO Orders
VALUES (OrderNum,
OrderDate,
CustID,
PNum,
UnitPrice,
QtyOrder,
TotalCost,
ShipDate,
QtyShipped,
OrderStatus,
NULL);
SELECT MaxNum,
SYSDATE,
&vCustID,
'&vPNum',
UnitPrice,
&vQty,
TotalCost,
ShipDate,
QtyShipped,
'Open',
Orders.ReasonNum
FROM CancelledOrder, Orders, Counter
WHERE Orders.ReasonNum = CancelledOrder.ReasonNum;
COMMIT;
Orders Table for reference
CREATE TABLE Orders
(
OrderNum NUMBER (4) PRIMARY KEY,
OrderDate DATE,
CustID CHAR (3),
PNum VARCHAR2 (3),
UnitPrice NUMBER,
QtyOrder NUMBER,
TotalCost NUMBER,
ShipDate DATE,
QtyShipped NUMBER,
OrderStatus VARCHAR2 (10),
ReasonNum NUMBER,
CONSTRAINT fk_CustID FOREIGN KEY (CustID) REFERENCES Customer (CustID),
CONSTRAINT fk_PNum FOREIGN KEY (PNum) REFERENCES Product (PNum),
CONSTRAINT fk_ReasonNum FOREIGN KEY
(ReasonNum)
REFERENCES CancelledOrder (ReasonNum)
);

I presume that INSERT should go along with SELECT, i.e.
insert into ...
select ... from
On your example:
INSERT INTO Orders (OrderNum, --> no VALUES keyword, but list of columns
OrderDate,
CustID,
PNum,
UnitPrice,
QtyOrder,
TotalCost,
ShipDate,
QtyShipped,
OrderStatus,
reasonnum) --> reasonnum instead of null
SELECT MaxNum,
SYSDATE,
&vCustID,
'&vPNum',
UnitPrice,
&vQty,
TotalCost,
ShipDate,
QtyShipped,
'Open',
Orders.ReasonNum
FROM CancelledOrder, Orders, Counter
WHERE Orders.ReasonNum = CancelledOrder.ReasonNum;
Also, check FROM & WHERE clauses: there are 3 tables involved with only one condition. You'll get - as a result - more rows than you expected, unless you fix that (or unless COUNTER table contains only 1 row).

For these examples, imagine two tables, a and b, with 3 columns each.
When you are inserting, the statement must either use:
Method A) Here we instruct the database to INSERT (to all or to specific columns) the results of a query. To do this, we write INSERT INTO SELECT ..... for example:
INSERT INTO table_a select table_b.* from table_b --Useful when we know how many columns table a and b have;
or
INSERT INTO table_a select b.column_2, b.column_3, b.column_1 from table_b --Usefull if b had more columns and we want those three, or if the order of the columns of b needs id different from the order of the columns of a
[In this case, all columns of table a will be filled with the respective columns from the rows of table b that the select part of the query returns]
or:
INSERT INTO table_a (tab_a_column1, tab_a_column3) select b.column_1, b.column_3 from table_b
[In this case, only the specified columns of table a will be filled with the columns from table b that the select part of the query returns]
-> Note that in these examples the VALUES keyword is never used
Method B) In this case we instruct the database to insert a sinlge new row with specific values into the table (to all or to specific columns of the table). In this method we do not use a select query at all:
INSERT INTO table_a VALUES ( 1, 'asdf', 5658 ) ;
In this example we just give some values to be inserted. They will be put in the corresponding columns of table_a, in the order that the columns are in the table.
INSERT INTO table_a (tab_a_column1, tab_a_column3) VALUES (1, 5658);
The numbers 1 and 5658 will be inserted to the first and third column, while the second one will be left NULL
So, when using VALUES, we are only inserting one row.
But when using Method A, our one statement may insert any number of rows at one go. It all will depend on how many rows the SELECT part of the query returns.
NOTE: the select part of the query in method A has no limit to how complex it can be. For example it can have multiple joins, where clauses, group by ... and more.
A good link that explains INSERT INTO can be found here:
https://www.techonthenet.com/sql/insert.php

Related

How to pick specific date from a field of type timestamp in Oracle

Hi I'm trying to create a query that would bring the tablets sold on a particular date in oracle. the field data type is timestamp.
Here's the query
SELECT
Order_detail.order_detail_id,
product_name AS product,
Product_categ_type.product_categ_type AS category,
Order_line.qty AS qty,
order_date
FROM Product, Order_detail, Order_line, Product_categ_type
WHERE Order_detail.order_detail_id = Order_line.order_detail_id
AND Product.product_id = Order_line.product_id
AND Product.product_categ_type_id = 3
AND Product_categ_type.product_categ_type LIKE 'TB%'
AND order_date = TO_DATE('2022-12-02' ,'yyyy,mm,dd')
The query works but it is not returning any data and I think the problem is in how I'm picking the date
-- INSERT INTO PRODUCT TABLE
INSERT INTO Product (product_id,product_categ_type_id,product_name,price,stock_qty) VALUES (174,1,'iWatch',454,183);
INSERT INTO Product (product_id,product_categ_type_id,product_name,price,stock_qty) VALUES (194,3,'Samsung Galaxy Tab',398,114);
INSERT INTO Product (product_id,product_categ_type_id,product_name,price,stock_qty) VALUES (139,1,'Fitness Tracker',312,122);
INSERT INTO Product (product_id,product_categ_type_id,product_name,price,stock_qty) VALUES (150,3,'iPad',366,189);
-- INSERT INTO PRODUCT CATEGORY TABLE
INSERT INTO Product_categ_type (product_categ_type_id,product_categ_type) VALUES (1,'AC');
INSERT INTO Product_categ_type (product_categ_type_id,product_categ_type) VALUES (2,'SP');
INSERT INTO Product_categ_type (product_categ_type_id,product_categ_type) VALUES (3,'TB');
-- INSERT INTO Order detail
INSERT INTO Order_detail (order_detail_id,product_id,customer_id,emp_id) VALUES (144,150,196,113);
INSERT INTO Order_detail (order_detail_id,product_id,customer_id,emp_id) VALUES (183,139,140,197);
INSERT INTO Order_detail (order_detail_id,product_id,customer_id,emp_id) VALUES (172,194,185,113);
-- INSERT INTO Order line
INSERT INTO Order_line (product_id,order_detail_id,qty) VALUES (150,144,1);
INSERT INTO Order_line (product_id,order_detail_id,qty) VALUES (139,183,5);
INSERT INTO Order_line (product_id,order_detail_id,qty) VALUES (194,172,1);
Use a 24-hour range:
AND order_date >= DATE '2022-12-02'
AND order_date < DATE '2022-12-03'
Alternatively, you could use TRUNC to truncate the column back to midnight of the same day so that you do not need to worry about the time component:
AND TRUNC(order_date) = DATE '2022-12-02'
However, in that case, Oracle would not be able to use any index on the order_date column and would need to use a function-based index on TRUNC(order_date) so it is often better to use ranges.

Copy data on parent and child table

I have two database tables. What I need to do is to copy specific data from one storage to another, but also keep the mapping to the photos. First part I can do easily writing
INSERT INTO item (storage_id, price, quantity, description, document_id)
SELECT 10, price, quantity, description, document_id
FROM item
WHERE quantity >= 10 AND price <= 100
but after that newly inserted items does not have photos. Note, that document_id field is unique for not copied items.
Assuming id columns are auto-generated surrogate primary keys, like a serial or IDENTITY column.
Use a data-modifying CTE with RETURNING to make do with a single scan on each source table:
WITH sel AS (
SELECT id, price, quantity, description, document_id
FROM item
WHERE quantity >= 10
AND price <= 100
)
, ins_item AS (
INSERT INTO item
(storage_id, price, quantity, description, document_id)
SELECT 10 , price, quantity, description, document_id
FROM sel
RETURNING id, document_id -- document_id is UNIQUE in this set!
)
INSERT INTO item_photo
(item_id, date, size)
SELECT ii.id , ip.date, ip.size
FROM ins_item ii
JOIN sel s USING (document_id) -- link back to org item.id
JOIN item_photo ip ON ip.item_id = s.id; -- join to org item.id
CTE sel reads all we need from table items.
CTE ins_item inserts into table item. The RETURNING clause returns newly generated id values, together with the (unique!) document_id, so we can link back.
Finally, the outer INSERT inserts into item_photo. We can select matching rows after linking back to the original item.id.
Related:
Insert New Foreign Key Row for new Strings
But:
document_id field is unique for not copied items.
Does that guarantee we are dealing with unique document_id values?
Given that document_id is the same in the two sets, we can used that to ensure that after the first copy, that all duplicate entries that have photos are copied across.
Note: This is still a dirty hack, but it will work. Ideally with data synchronizations we make sure that there is a reference or common key in all the target tables. You could also use output parameters to capture the new id values or use a cursor or other looping constructs to process the records 1 by 1 and copy the photos at the same time instead of trying to update the photos after the initial copy stage.
This query will insert photos for items that do NOT have photos but another item with the same document_id does have photos.
INSERT INTO item_photo (item_id, "date", size)
SELECT "source_photo".item_id, "source_photo"."date", "source_photo". Size
FROM item "target_item"
INNER JOIN item "source_item" on "target_item".document_id = "source_item".document_id
INNER JOIN item_photo "source_photo" ON "source_item".id = "source_photo".item_id
WHERE "target_item".id <> "source_item".id
AND NOT EXISTS ( SELECT id FROM item_photo WHERE item_id = "target_item".id)
AND source_item.id IN (
SELECT MIN(p.item_id) as "item_id"
FROM item_photo p
INNER JOIN item i ON p.item_id = i.id
GROUP BY document_id
)

Remove clients who don't have 2 rows by their name in SQL

What I'm trying to do is to filter by the clients that registered twice in the DB. This as I need to know who of them came at least twice, that is why I´m working with a table that registers every time they registered in the system as it follows:
order #
client
date
One
Andrew
XX
Two
Andrew
XX+1
Three
Andrew
XX+2
One
David
YY
One
Marc
ZZ
Two
Marc
ZZ+1
In this case I want to delete David´s record, as I only want people who has order numbers distinct than "one".
I tried this SQL:
select *
from table
where order_number > 1
however what this does is remove all the rows of the first orders, including the ones that came back.
Does somebody know an easy way for me to compare row names and filter by that or just how could I delete those rows in which there are clients with only one entry?
you need something like this :
select * from yourtable
where not exists (select 1 from yourtable where order_number >1)
or:
select client
from tablename
group by client
having count(*) > 1
CREATE TABLE records (
ID INTEGER PRIMARY KEY,
order_number TEXT NOT NULL,
client TEXT NOT NULL,
date DateTime NOT NULL
);
INSERT INTO records VALUES (1,'ONE', 'Adrew', '01.01.1999');
INSERT INTO records VALUES (2, 'TWO','Adrew', '02.02.1999');
INSERT INTO records VALUES (3, 'THREE','Adrew', '03.03.1999');
INSERT INTO records VALUES (4, 'ONE', 'David', '01.01.1999');
INSERT INTO records VALUES (5, 'ONE','Marc', '01.01.1999');
INSERT INTO records VALUES (6, 'TWO','Marc', '01.03.1999');
DELETE FROM records WHERE ID in
(
SELECT COUNT(client) as numberofclient FROM records
Group By client Having Count (client) > 1
);

SQL create a full part list out of a given part list (iteration)

I have a problem with a given task from my SQL lecture.
In the task there is a database given with a list of parts of three robots and another list, where these parts are linked to parts from the first list, that they are made of, if they are made of other parts.
The databasess can be generated with:
CREATE TABLE part (
part_id BIGINT PRIMARY KEY,
part_namevarchar(64)NOTNULL
);
CREATE TABLE part_part (
object_id BIGINT,
part_id BIGINT,
quantity INT NOT NULL,
PRIMARY KEY(object_id, part_id)
);
ALTER TABLE part_part
ADD CONSTRAINT part_id_fkey FOREIGNKEY (part_id) REFERENCES part(part_id)
ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE part_part
ADD CONSTRAINT object_id_fkey FOREIGN KEY(object_id)REFERENCES part(part_id)
ON UPDATE CASCADE ONDELETE CASCADE;
INSERT INTO part(part_id, part_name)
VALUES
(0,'CPU A'),
(1,'Cables'),
(2,'Motherboard 3xy'),
(3,'Motor ayX'),
(4,'Arm'),
(5,'Body'),
(6,'Leg'),
(7,'Wheel'),
(8,'Motherboard 7ax'),
(9,'Joint'),
(10,'Motor Z1238'),
(11,'Hammer'),
(12,'Screw A'),
(13,'Screw B'),
(14,'Screw C'),
(15,'Robo 1000'),
(16,'CPU B'),
(17,'CPU C'),
(18,'Robo 2000'),
(19,'Screwdriver'),
(20,'Robo 3000');
INSERT INTO part_part
(object_id, part_id, quantity)
VALUES
(5,2,1),
(5,0,1),
(5,3,2),
(5,1,5),
(5,12,3),
(4,9,3),
(4,10,3),
(4,13,13),
(6,3,2),
(6,7,4),
(15,4,2),
(15,11,2),
(15,5,1),
(15,6,1),
(18,4,2),
(18,11,2),
(18,5,1),
(18,6,2),
(18,16,1),
(20,4,3),
(20,11,1),
(20,19,1),
(20,5,1),
(20,6,1),
(20,16,1),
(20,17,1);
Now the task is to get the list of all parts and subparts needed for the "Robo 3000" and their quantity.
I got as far as:
WITH part2(part_name1, subpart_id, top_quantity, top_part_id, part_name) AS(
WITH part1(part_name, subpart_id, quantity) AS(
WITH subpart1(object_id, subpart_id, quantity) AS(SELECT * FROM part_part)
SELECT part_name, subpart_id, quantity FROM subpart1
JOIN part ON part.part_id = subpart1.object_id
WHERE part_name = 'Robo 3000'
)
SELECT * FROM part1
JOIN part ON part1.subpart_id = part.part_id
)
SELECT * FROM part2
JOIN part_part ON part2.top_part_id = part_part.object_id
ORDER BY top_part_id;
Which gives me a list of only subparts (the parts of all the parts from the robot, that need parts themselves) and also it doesn't consider, if parts are used multiple times, here the arm is used 3 times but its parts aren't multiplied with the quantity.
Also this is limited, since it only looks at the given part and the supp parts but not deeper if needed.
Is there a way to iterate through all the parts and make them into a big list in SQL?
The same way for example a java method would with a self calling method?
PostgreSQL supports recursive sQL which may be one way solve your problem. Below is a example using your data.
with recursive part_list as
(
(
select object_id as unit, object_id, part_id, quantity, quantity as totqty
from part_part
where object_id = 20
)
union
select pl.unit, pp.object_id, pp.part_id, pp.quantity, pp.quantity * pl.quantity
from part_part pp
join part_list pl
on pp.object_id = pl.part_id
)
select u.part_name as unit,
part.part_name,
sum(part_list.totqty) as total_parts
from part_list
join part u
on u.part_id = part_list.unit
join part
on part.part_id = part_list.part_id
group by u.part_name, part.part_name
order by 1,3;

INSERT multiple rows with SELECT and an array

In EXCEL/VBA I can program my way out of a thunderstorm, but in SQL I am still a novice. So apologies, after much Googling I can only get partway to a solution which I presume ultimately will be pretty simple, just not wrapping my head around it.
I need to create an INSERT script to add multiple rows in a 3-column table. A simple insert would be:
INSERT INTO table VALUES(StoreId, ItemID, 27)
First hurdle is dynamically repeat this for every StoreID in a different table. Which I think becomes this:
INSERT INTO table
SELECT (SELECT StoreID FROM Directory.Divisions), ItemID, 27)
If that is actually correct and would effectively create the 50-60 rows for each store, then I'm almost there. The problem is the ItemID. This will actually be an array of ItemIDs I want to feed in manually. So if there are 50 stores and 3 ItemIDs, it would enter 150 rows. Something like:
ItemID = (123,456,789,246,135)
So how can I merge these two ideas? Pull the StoreIDs from another table, feed in the array of items for the second parameter, then my hardcoded 27 at the end. 50 stores and 10 items should create 500 rows. Thanks in advance.
You can use into to insert into the target table. To generate itemid's you will have to use union all with your values and cross join on the divisions table.
select
d.storeid,
x.itemid,
27 as somecolumn
into targettablename
from Directory.Divisions d
cross join (select 123 as itemid union all select 456 union all select 789...) x
Edit: If the table to insert into isn't created yet, it should be created before inserting the data.
create table targettable as (store_id varchar(20), item_id varchar(20),
somecolumn int);
insert into targettable (store_id, item_id, somecolumn)
select
d.storeid,
x.itemid,
27
from Directory.Divisions d
cross join (select 123 as itemid union all select 456 union all select 789...) x
Firstly you need your array of item ids in a table of some sort. Either a permanent table, table variable or temporary table. For example using a temporary table, which you prefix with a hash symbol:
CREATE TABLE #ItemIds (item_id int)
INSERT INTO #ItemIds VALUES (1)
INSERT INTO #ItemIds VALUES (2)
...
INSERT INTO #ItemIds VALUES (10)
Then this should do the trick:
INSERT INTO table
SELECT StoreId, item_Id, 27
FROM Directory.Divisions, #ItemIds
The results set from the SELECT will be inserted into 'table'. This is an example of a cartesian join. Because there is no join condition, every row from Directory.Divisions is joined to every row in #ItemIds. Hence if you have 50 stores and 10 items, that will result in 50 x 10 = 500 rows.
You may declare table variable for item IDs and use CROSS JOIN to multiply division records to items: http://sqlfiddle.com/#!3/99438/1
create table Divisions(StoreId int)
insert into Divisions values (1), (2), (3)
declare #items table(ItemID int)
insert into #items values (5), (6), (7)
-- insert into target(stireid, itemid, otherColumn)
select d.StoreId, i.ItemID, 27
from Divisions d
cross join #items i