Want to update a column with a number value following specific query - sql

So this is my first question and first day here. Thanks in advance.
I want to perform the following query -
Put the fine on books_return if the duration is violated, otherwise put zero.
The duration is in book_issue. SO I figured out that I can calculate the difference between return_date and issue_date and if it is greater than 10 then fine_amount will update to 20; otherwise will update to zero. However, I am having trouble with the query statement which is the following -
UPDATE (
SELECT brt.fine_amount
FROM book_return brt, book_issue bi
WHERE brt.book_id = bi.book_id
AND brt.return_date - bi.issue_date > bi.issue_duration
) SET fine_amount = 20;
error - ORA-01779: cannot modify a column which maps to a non key-preserved table
How can I pull off this query?
EDIT: book_id and borrower_id are the composite primary keys of both tables.
related tables -

You can do what you want with merge. If you use update, you can use exists:
UPDATE book_return brt
SET fine_amount = 20
WHERE EXISTS (SELECT 1
FROM book_issue bi
WHERE brt.book_id = bi.book_id AND
brt.return_date - bi.issue_date > bi.issue_duration
);

Related

Find a single row and update it with nested queries

Good evening everyone, I'm trying to do an update on a Table but I can't really make it work
The feature needed is:
-Watch a field on a form, it contains the number of people that need to sit at the restaurant table.
-Find the first free table that has enough seats, set it as busy and assign a random waiter
Any idea?
more db infos:
Table "Waiters" is composed by ID(Autonumber),Name(Short Text). Has 2 names atm
Table "Tables" is composed by ID(Autonumber),Seats(Number),Busy(y/n),Waiter(short text). All tables have a fixed number of seats and have no Waiter + not busy
SOLUTION:
In the end i used "First" for the assignment and it works perfectly as it follows:
UPDATE Tables SET Tables.Waiter = DLookUp("FirstName","TopWtr")
WHERE ID IN (SELECT FIRST (ID)
FROM Tables
WHERE Seats >= Val(Forms!Room!Text12) AND Waiter Is Null);
Top wasn't working because it was returning multiple records - every table with same number of seats - and couldn't make it work with DISTINCT. This works probably because the table is already ordered by seats
Thanks to June7 for the input
Cannot SET a field value to result of a SELECT subquery - SELECT returns a dataset not a single value. Can return a single value with domain aggregate function.
Build a query object named TopWtr:
SELECT Top 1 ID FROM Waiters ORDER BY Rnd(ID);
Then use DLookup to pull that value. The Busy field seems redundant because if table has a waiter assigned that would indicate busy.
UPDATE Tables SET Tables.Waiter = DLookUp("ID","TopWtr"), Tables.Busy = True
WHERE ID IN (SELECT TOP 1 ID FROM Tables
WHERE Seats >= Val(Forms!Room!Testo17) AND Waiter Is Null
ORDER BY Seats)
An INNER JOIN may be preferable to WHERE clause:
UPDATE Tables INNER JOIN (SELECT TOP 1 ID FROM Tables
WHERE Seats >= Val(Forms!Room!Testo17) AND Waiter Is Null
ORDER BY Seats) AS T1
ON Tables.ID = T1.ID
SET Tables.Waiter = DLookUp("ID","TopWtr"), Tables.Busy = True

SQL - Update all rows with certain condition

Hi i want to do is a query which do the following thing:
If i execute the query ,all rows will set to 0 except certain id in the where(which supposed to be always 1 and only one row can be active at the moment)
tbl_menu
id | serial
starter | varchar
plate | varchar
beverage | varchar
status | smallint
So if i have one registry with status in 1 and everything else in 0, when i execute this query, certain id i choose will change to 1 and the others to 0
also only one row status = 1
Try this:
UPDATE tbl_menu
set status = CASE WHEN id = 4 or status = 1 THEN 1 ELSE 0 END;
I think you have two choices with the design as it is.
1) Do it with two easy queries.
2) Write one more complicated query with a case statement.
I personally like easy:
UPDATE tblmenu SET status = 0 WHERE status = 1;
UPDATE tblmenu SET status = 1 WHERE id = n;
Although, having said that, I think a better approach is this...
Get rid of your status column
Create a new table called, say tblstatus with one column id
One record with the id of the record
Foreign key to your main table
Now all you have to do is:
UPDATE tblstatus SET id = n;
Faster, easier, more robust...
This is a basic update statement. But if you could give more info on the column names and on what condition you want to do the updates it would be helpful.
UPDATE tbl_menu SET (column) = value
WHERE (condition)
This doesn't solve the problem of the update, but it does solve the problem of enforcing that (at most) one row is active. Use a partial unique index:
create unique index unq_menu_active on tblmenu(flag) where flag = 1;

How to compare records and update one column

It is a little bit tricky for me so I need your help :)
I want to update the column Relevant to 0 WHERE Contract_Status_Code is 10 OR the Date_Contract_start YEAR is the same AND the Ranking_Value is lower than the other one ON all records that have the same VIN.
So I want to compare all records which have the same VIN.
Few examples to illustrate it:
I have there two records with the VIN = 123456. One of them (ID = 6847) has a higher Ranking_Value (7) than the other one (3). The YEAR is the same as well so I want to update the column relevant to 0 where the ID is 8105.
Two records with the VIN = 654321. Both of them have the same Ranking_Value but the record with the id = 11012 has the value 10 for the column Contract_Status_Code so I want to update the relevant column to 0 where the ID = 11012.
The last two records... They have the VIN = 171819. The first one (ID = 11578) has the higher Ranking_Value. But they have a different year where the contract has started. So I don't want to update both.
It is also possible that there are three or four records with the same VIN.
I hope you understand my problem. I'm from Germany so sorry for my English :)
By considering your ID column as unique or Identity column, I can suggest you the below query for your solution:
With cte
As
(Select a.Id, a.VIN From Table a
Join (Select max(Ranking_Value) ranks,VIN From Table Group By VIN, Year(Date_Contract_start)) b
on a.VIN=b.VIN And a.Ranking_Value = b.ranks)
update table
set Relevant = 0
where (Contract_Status_Code = 10) Or
ID Not In (Select id from cte)
update table1
set Relevant = 0
where Contract_Status_Code = 10
or (VIN,Year,Ranking_value) not in(
select VIN,Year,max(Ranking_Value)
from table1
group by VIN,Year
)

Issue with UPDATE QUERY using EXISTS clause causing slow Tablespace scans in DB2

Our workplace has a database with a client table that holds 5 million records. Each time a client is updated, another row is added to a client_history table that holds 100 million records. All columns in the Client table are indexed. Only the Primary Key (ID), Foreign Key (FK_Client_ID) and Creation Timestamp in the Client History table are indexed.
I've been asked to update several hundred thousand client records, but only if the corresponding client history record indicates that the client record has not been updated since a certain date (e.g. 19th September 2012).
I've written an SQL update query that uses an EXISTS clause. I've been told by the DBA's that I shouldn't use an EXISTS clause, as this would trigger a tablespace scan that would slow down execution of the query. This is obviously an issue when updating several hundred thousand client records -
UPDATE Client_History SET Surname = 'MisterX',
Update_Timestamp = CURRENT_TIMESTAMP
WHERE (FK_Client_ID = 123 AND ID = 456)
AND NOT EXISTS
(SELECT *
FROM Client
WHERE Client.Client_Id = Client_History.FK_Client_ID
AND Client_History.Update_Timestamp > TIMESTAMP('2012-09-21-00:00:00')
AND Client_History.Update_Timestamp < TIMESTAMP('4000-12-31-00:00:00')
AND Client_History.Creation_Timestamp < NAME.Update_Timestamp);
Can anyone think of a better solution?
A shot in the dark: try hoisting all the constants up into the main query (where they belong)
UPDATE Client_History ch
SET Surname = 'MisterX'
, Update_Timestamp = CURRENT_TIMESTAMP
WHERE ch.FK_Client_ID = 123
AND ch.ID = 456
AND ch.Update_Timestamp > TIMESTAMP('2012-09-21-00:00:00')
AND ch.Update_Timestamp < TIMESTAMP('4000-12-31-00:00:00')
AND ch.Creation_Timestamp < NAME.Update_Timestamp
AND NOT EXISTS (
SELECT *
FROM Client cl
WHERE cl.Client_Id = ch.FK_Client_ID
)
;
BTW: what is NAME ? Some kind of pseudo table, like Oracle's dual ?

Update with multiple rows

i am using UPDATE to update all records in the table with value from another table:
UPDATE x.ADR_TEMP SET LOCATIONID = (SELECT ID FROM x.OBJECTRELATIONSHIP WHERE PROPERTYCLASS = 'PHYSICALLOCATION')
in both tables are the same number of records. I just need to read id from one table and put them into another.
I have error: ORA-01427: single-row subquery returns more than one row
I am new in this subject and suspect that solution is very simple. Please help me
UPDATE x.ADR_TEMP SET LOCATIONID = (
SELECT ID
FROM x.OBJECTRELATIONSHIP
WHERE PROPERTYCLASS = 'PHYSICALLOCATION' AND x.ADR_TEMP.relatedKey = x.OBJECTRELATIONSHIP.relatedKey )
if your tables are related to each other with some way like this(relatedKey is a column which relates to the second table mentioned), you can try this one.(not sure or perfect)