I am trying to execute a simple SQL update-set-from statement in Oracle, which looks like the one below:
update
table1 t1
set
t1.col1=t2.col1
from
(select distinct t1.col1 from table1 t1 where t1.col2='xxx') as t2
where
t1.col1='yyy';
I haven't used from with update-set before, but this syntax looks okay to me. Yet it fails with this error:
Error report -
SQL Error: ORA-00933: SQL command not properly ended
00933. 00000 - "SQL command not properly ended"
*Cause:
*Action:
My desired result is for the inner select to return a single record, which then gets inserted/updated into table1's col1.
Also, should I be using a different alias thant1 for table1 in the inner select statement, considering that I have already used t1 in the update statement?
Syntax should be
update table t1 set
t1.col1 = (select distinct t2.col1
from table1 t2
where t2.col2 = 'xxx')
where t1.col1 = 'yyy';
Note that DISTINCT doesn't necessarily mean that SELECT will return a single value; if it does not, you'll end up in TOO-MANY-ROWS error.
Related
I tried to delete an entry from table1 based on criteria on table2. (id in table1 is foreign key from table2)
I tried all those below and all returned with syntax errors.
take 1:
delete table1.* from table1 inner join table2 on table1.id=table2.id where table2.column3=21 and table2.column4=59;
Error: near "table1": syntax error
take 2:
delete table1 from table1 inner join table2 on table1.id=table2.id where table2.column3=21 and table2.column4=59;
Error: near "table1": syntax error
take 3:
delete from table1 inner join table2 on table1.id=table2.id where table2.column3=21 and table2.column4=59;
Error: near "inner": syntax error
Anyone knows what are the correct syntax?
If this is the wrong approach, what is the correct way to achieve my goal?
Really appreciate it.
No Join in SqlLite DELETE, by the look of it, but you could use exists:
delete
from table1
where exists
(select 1
from table2
where table1.id=table2.id
and table2.column3=21
and table2.column4=59
);
Since SQLite does not support JOIN yet in outer query of DELETE statements, consider using subquery with IN or EXISTS:
DELETE FROM table1
WHERE id IN (
SELECT id
FROM table2
WHERE table2.column3 = 21
AND table2.column4 = 59
)
DELETE FROM table1
WHERE EXISTS (
SELECT 1
FROM table2
WHERE table1.id = table.id
AND table2.column3 = 21
AND table2.column4 = 59
)
I get the error
[Code: 10002, SQL State: 42000]
Error while compiling statement: FAILED: SemanticException [Error 10002]: Line 11:60 Invalid column reference 'FIELD3'
when running the following query:
CREATE TABLE NEW_TABLE
AS
SELECT
T1.*,
T2.*,
T3.*
FROM
OLD_TABLE1 T1
LEFT JOIN
OLD_TABLE2 T2 ON (T1.FIELD1 = T2.FIELD1)
LEFT JOIN
OLD_TABLE3 T3 ON (T1.FIELD3 = T3.FIELD3);
What is the potential issue of the above query? I double checked that the FIELD3 exists in OLD_TABLE1 and OLD_TABLE3.
One major issue you have is that duplicated column names in the table. At the very least, the JOIN conditions will introduce duplicates. There might be other duplicates as well.
List the columns you want explicitly:
CREATE TABLE NEW_TABLE AS
SELECT . . . -- list column names explicitly
FROM OLD_TABLE1 T1 LEFT JOIN
OLD_TABLE2 T2
ON T1.FIELD1 = T2.FIELD1 LEFT JOIN
OLD_TABLE3 T3
ON T1.FIELD3 = T3.FIELD3;
This problem may occur with CREATE TABLE. That said, it is more common with aggregation queries.
I have the following SQL code (this is how much I've got so far):
MERGE INTO SCHEMA1.TABLE_1 table1 USING
(
SELECT DISTINCT table2.column1,
view1.column2
FROM SCHEMA2.TABLE_2 table2
LEFT JOIN SCHEMA2.VIEW_1 view1
ON table2.column2 = view1.column3
) t2 ON (table1.column3 = t2.column1 )
WHEN MATCHED THEN
UPDATE
SET table1.column4 = t2.column2;
The following is the definition of VIEW_1 :
CREATE VIEW SCHEMA_2.VIEW_1
AS (SELECT
SCHEMA_2.TABLE_1.COLUMN_1,
SCHEMA_2.TABLE_2.COLUMN_1,
SCHEMA_2.TABLE_2.COLUMN_2,
SCHEMA_2.TABLE_2.COLUMN_3,
SCHEMA_2.TABLE_5.COLUMN_1,
SCHEMA_2.TABLE_6.COLUMN_1,
SCHEMA_2.TABLE_6.COLUMN_2,
SCHEMA_2.TABLE_6.COLUMN_3,
SCHEMA_2.TABLE_6.COLUMN_4,
SCHEMA_2.TABLE_7.COLUMN_1,
SCHEMA_2.TABLE_7.COLUMN_2,
SCHEMA_2.TABLE_8.COLUMN_1
FROM SCHEMA_2.TABLE_1
INNER JOIN SCHEMA_2.TABLE_2
ON SCHEMA_2.TABLE_1.COLUMN_1 = SCHEMA_2.TABLE_2.COLUMN_2
INNER JOIN SCHEMA_2.TABLE_5
ON SCHEMA_2.TABLE_1.COLUMN_4 = SCHEMA_2.TABLE_5.COLUMN_3
LEFT OUTER JOIN SCHEMA_2.TABLE_6
ON SCHEMA_2.TABLE_2.COLUMN_2 = SCHEMA_2.TABLE_6.COLUMN_4
LEFT OUTER JOIN SCHEMA_2.TABLE_7
ON SCHEMA_2.TABLE_2.COLUMN_1 = SCHEMA_2.TABLE_8.COLUMN_5
);
But I'm getting the below error message:
Error report -
SQL Error: ORA-30926: unable to get a stable set of rows in the source tables
30926. 00000 - "unable to get a stable set of rows in the source tables"
*Cause: A stable set of rows could not be got because of large dml
What causes the error? Where to change in the code to make it work?
Thanks for helping out!
For this example your problem is definitely in the USING subquery. This query produces more than one value of table2.column1:
SELECT DISTINCT table2.column1,
view1.column2
FROM SCHEMA2.TABLE_2 table2
LEFT JOIN SCHEMA2.VIEW_1 view1
ON table2.column2 = view1.column3
So the ON clause will match the same row(s) in table1 more than once:
ON (table1.column3 = t2.column1 )
Oracle cannot figure out which value of t2.column2 should be used in the UPDATE, so it hurls ORA-30926.
Using distinct in the subquery doesn't help because that gives permutations of all the columns. You need to write a subquery which will produce unique values of t2.column1 across all rows, or add another identifying column(s) to generate a unique key you can join to table1.
In my experience, this error is returned, not only when the USING clause returns more than one row for a row in the MATCH table, but also frequently when it cannot be sure that only one row will be returned (even if there are no actual cases of multiple rows being returned). To force the parser to accept the query in cases like this, I usually resort to using a GROUP BY on the MATCH..ON column(s).
MERGE INTO SCHEMA1.TABLE_1 table1 USING
(
SELECT table2.column1,
MAX(view1.column2) as column2
FROM SCHEMA2.TABLE_2 table2
LEFT JOIN SCHEMA2.VIEW_1 view1
ON table2.column2 = view1.column3
GROUP BY table2.column1
) t2 ON (table1.column3 = t2.column1 )
WHEN MATCHED THEN
UPDATE
SET table1.column4 = t2.column2;
I have 2 tables:
I want to update my table1 records with the suitable age, which can be found in table2. Unique identifier is the BVD_ID_NUMBER. I tried to do this using the following code
UPDATE table1
SET table1.age =
(select table2.age2
from
(select distinct table2.BVD_ID_NUMBER, table2.age2
FROM table1
inner JOIN table2
on table1.ACQUIROR_BVD_ID_NUMBER=table2.BVD_ID_NUMBER)
where table2.BVD_ID_NUMBER=table1.ACQUIROR_BVD_ID_NUMBER);
I received the following error:
SQL Error: ORA-00904: "ORBIS_DISTINCT"."BVD_ID_NUMBER": invalid identifier
00904. 00000 - "%s: invalid identifier"
Any help?
Hmmm. You have overcomplicated your query. Usually, when using correlated subqueries, there is no reason to mention the outer table in the inner subquery. Oracle doesn't allow scoping beyond one level for correlated subqueries, so you need to simplify for the correlation clause:
UPDATE table1 t1
SET age = (select t2.age2
from table2 t2
where t1.ACQUIROR_BVD_ID_NUMBER = t2.BVD_ID_NUMBER
);
This is likely to cause a "subquery returns more than one row" type of error. To fix that, use aggregation or rownum = 1:
UPDATE table1 t1
SET age = (select t2.age2
from table2 t2
where t1.ACQUIROR_BVD_ID_NUMBER = t2.BVD_ID_NUMBER and
rownum = 1
);
I tried doing this but it failed.
SELECT table2.ID, table1.* FROM table2
LEFT JOIN table1 ON table1.ID = table2.table1ID
How do you select all columns from a table?
EDIT: There is no error in the above query. I don't know what caused the error but the code is now working.
You had field names conflict as both tables have ID field. You must to
SELECT table2.ID as t2_id, table1.* FROM table2
LEFT JOIN table1 ON table1.ID = table2.table1ID
What you have is syntactically correct, exactly what did you mean by it failed? Did you get an error message or just not the results you wanted? (BTW it is a bad practice to select *, only return the columns you need. In this case you do not need all the columns as the id field in table1 will have the exact same data as the file din table 2 it is joined to)
SELECT t2.ID, t1.* FROM table2 t2
LEFT JOIN table1 t1 ON t1.ID = t2.table1ID
this works on sql 2000+
If I am working inside a stored procedure where I have a defined #Table data type, there is no issue with using select table.* especially if I am using it for an output SELECT at the end. So the comment about production servers and network traffic in this case is meaningless as the entire stored procedure executes in memory. A select.* in this case is merely returning all the columns which have been defined ahead of time.