how to update table with join? - plsql

In oracle db i have a table which include 2 varchar columns - new_val, old_val.
I need to update multiple tables which has several columns which include in their values the old_val from the 1st table mension above, and replace them with "new_val" from that table.
tried to perform the following but got an error:
UPDATE (SELECT a.account_id, b.new_val, b.old_val FROM
any_table a JOIN val_table b ON a.account_id like
'%'||b.old_val||'%') SET account_id=
replace(account_id,old_val ,new_val);
Error: ORA-01779: cannot modify a column which maps to a non key-preserved table
I understand the error but can't find the proper solution.
Thanks,

Try:
UPDATE ANY_TABLE a
SET account_id= (
SELECT replace(a.account_id,b.old_val ,b.new_val)
FROM VAL_TABLE b
WHERE a.account_id like '%'||b.old_val||'%'
)
WHERE EXISTS (
SELECT 1 FROM VAL_TABLE b
WHERE a.account_id like '%'||b.old_val||'%'
);

Related

DELETE from same table used in the WHERE

I have the following query that is supposed to delete from a table with a circular FK requirement;
DELETE FROM question
WHERE defaultGotoQuestionId IN (
SELECT id from question WHERE facilityId IN (
SELECT id FROM facility WHERE customerId NOT IN (1,76)
)
);
But I get the following error;
Table is specified twice, both as a target for 'DELETE' and as a separate source for data
I understand the error message - that I can't DELETE from a TABLE that I am specifying in the WHERE - I just can't seem to work out how to solve it, for myself.
I saw a few examples of using a join - but perhaps I am having an off day - because I have been iterating through copy/paste examples - but still can't manage it.
It works as a SELECT : In that the result gives me the records I want to delete;
SELECT id FROM question
WHERE defaultGotoQuestionId IN (
SELECT id from question WHERE facilityId IN (
SELECT id FROM facility WHERE customerId NOT IN (1,76)
)
);
Thanks for any help!
What version of MariaDB are you using?
DELETE :: Same Source and Target Table
Until MariaDB 10.3.1, deleting from a table with the same source and target was not possible. From MariaDB 10.3.1, this is now possible.
See dbfiddle.
In older versions of MariaDB (or in MySQL, for example), one option you can use is:
DELETE
`question`
FROM
`question`
INNER JOIN (
SELECT
`id`
FROM
`question`
WHERE
`defaultGotoQuestionId` IN (
SELECT
`id`
FROM
`question`
WHERE
`facilityId` IN (
SELECT
`id`
FROM
`facility`
WHERE
`customerId` NOT IN (1, 5)
)
)
) `der` ON
`question`.`id` = `der`.`id`;
See dbfiddle.

Oracle - Updating with Join 3 tables

I have 3 tables: inventory as table 1, buy_transaction as table 2, and po_data as table 3.
These are the queries I tried:
update vnt_inventory_tab.quantity
set vnt_inventory_tab.quantity = quantity + (SELECT pdt.quantity
FROM vnt_po_data_tab pdt JOIN vnt_buy_trnsctn_tab bt ON pdt.po_no = bt.po_no
WHERE pdt.po_no = :p_po_no)
where VNT_INVENTORY_TAB.CODE = VNT_PO_DATA_TAB.CODE;
It return as table doesn't exist. I'm not sure where I put wrong because when I do the sub-query it returns exactly the number I want to update into the inventory.
Help me pls
Syntax UPDATE statement requires only table-Name (not a specific column like yours) after the keyword update. More details see Oracle docs

Update row with value from next row sqlite

I have the following columns in a SQLite DB.
id,ts,origin,product,bid,ask,nextts
1,2016-10-18 20:20:54.733,SourceA,Dow,1.09812,1.0982,
2,2016-10-18 20:20:55.093,SourceB,Oil,7010.5,7011.5,
3,2016-10-18 20:20:55.149,SourceA,Dow,18159.0,18161.0,
How can I populate the 'next timestamp' column (nextts) with the next timestamp for the same product (ts), from the same source? I've been trying the following, but I can't seem to put a subquery in an UPDATE statement.
UPDATE TEST a SET nextts = (select ts
from TEST b
where b.id> a.id and a.origin = b.origin and a.product = b.product
order by id asc limit 1);
If I call this, I can display it, but I haven't found a way of updating the value yet.
select a.*,
(select ts
from TEST b
where b.id> a.id and a.origin = b.origin and a.product = b.product
order by id asc limit 1) as nextts
from TEST a
order by origin, a.id;
The problem is that you're using table alias for table in UPDATE statement, which is not allowed. You can skip alias from there and use unaliased (but table-name prefixed) reference to its columns (while keeping aliased references for the SELECT), like this:
UPDATE TEST
SET nextts = (
SELECT b.ts
FROM TEST b
WHERE b.id > TEST.id AND
TEST.origin = b.origin AND
TEST.product = b.product
ORDER BY b.id ASC
LIMIT 1
);
Prefixing unaliased column references with the table name is necessary for SQLite to identify that you're referencing to unaliased table. Otherwise the id column whould be understood as the id from the closest[*] possible data source, in which case it's the aliased table (as b alias), while we're interested in the unaliased table, therefore we need to explicitly tell SQLite that.
[*] Closest data source is the one listed in the same query, or parent query, or parent's parent query, etc. SQLite is looking for the first data source (going from inner part to the outside) in the query hierarchy that defines this column.

Add column to a table if not exist

I have a problem to add a new column to a SQLITE table if this column is not already exist.
I have try with this code but i don’t know why it wont execute:
IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'mytable' AND COLUMN_NAME = 'mynewcolumn')
BEGIN
ALTER TABLE mytable ADD COLUMN mynewcolumn TEXT
END
I get an Exception error :
error: near "IF": syntax error
This is the solution i select :
1- I do PRAGMA table_info :
pragma table_info(MyTable)
This command gives all the informations about all the columns of the table. each row correspand to the information of a column.
This commande return an output table with 4 columns : cid, name, type, notnull, dft value, pk
2- I read all the rows from "PRAGMA table_info (MyTable)", and i compare the column "name" with the name of the column i want to check if exist.
3- If Column exist then i dont do anything
4- but if the column doen't exist then, here i add the column to my table using this commade :
ALTER TABLE MyTable ADD COLUMN NewColumn TEXT;
this is work for me, and do the job correctly.
To test whether a column exists, execute PRAGMA table_info and check if the column name appears in the result.

Why do I get the error "Error: no such column: main.<tablename>.<columname>" although it exists?

This works:
sqlite> .databases
seq name file
--- --------------- ----------------------------------------------------------
0 main /path/to/db
2 uni /path/to/db
also this:
sqlite> pragma main.table_info(tsv_storage);
0|id|int|0||0
1|seqid|text|0||0
...
and this:
sqlite> select count(*) from main.tsv_storage;
198159
and also the attached database works:
sqlite> select * from uni.fasta_storage where uni.fasta_storage.id = 1;
1 MASNTVSAQ... Q197F8.1 002R_IIV3 Uncharacterized protein 002R Q197F8
but this not:
sqlite> select main.tsv_storage.seqid where main.tsv_storage.id=8;
Error: no such column: main.tsv_storage.seqid
EDIT:
and I have also problems with this, do I have to join the tables?
insert into main.tsv_storage(seqlength) select length(fasta) from
uni.fasta_storage where uni.fasta_storage.title = main.tsv_storage.seqid;
Error: no such column: main.tsv_storage.seqid
It happens for all columns, not only seqid. I think I did everything that is explained here: http://sqlite.awardspace.info/syntax/sqlitepg12.htm
What am I missing?
sqlite> select * from main.tsv_storage.seqid where main.tsv_storage.id=8;
You have not defined where to look for the selection. You need to tell the query what fields to search within the table, then define which table you are searching. The select * portion tells the query to look in all fields within the table. The from portion of the query tells the processes what table to look in. And lastly the where portion tells the query what to match when looking.
When using INSERT ... SELECT ..., the SELECT part must be valid query.
You cannot access a column like main.tsv_storage without having the table in the FROM clause:
INSERT INTO main.tsv_storage(seqlength)
SELECT length(fasta)
FROM uni.fasta_storage, main.tsv_storage
WHERE uni.fasta_storage.title = main.tsv_storage.seqid;
And the entire commands looks suspicious.
Are you sure you don't want to update the values in the seqlength column for existing records?
In that case, you would use something like this:
UPDATE main.tsv_storage
SET seqlength = (SELECT length(fasta)
FROM uni.fasta_storage
WHERE uni.fasta_storage.title = main.tsv_storage.seqid);

Resources