Invalid Identifier on Update (Oracle) - sql

I try to execute following command:
UPDATE DB_TEST.STOCK_ITEMS
SET STATUS = (SELECT *
FROM (SELECT STOCK_ITEM_STATUS
FROM DB_TEST.STOCK_ITEMS_HISTORY
WHERE STOCK_ITEM_ID = DB_TEST.STOCK_ITEMS.ID
ORDER BY CHANGED_ON DESC, ID DESC)
WHERE ROWNUM <= 1)
WHERE EXISTS (SELECT *
FROM DB_TEST.STOCK_ITEMS_HISTORY
WHERE STOCK_ITEM_ID = DB_TEST.STOCK_ITEMS.ID);
But I get the error:
SQL-Error: ORA-00904: "DB_TEST"."STOCK_ITEMS"."ID": invalid identifier
I looked up the Oracle error, but all I get is that I supposedly used a wrong or missing column name, but the DB_TEST.STOCK_ITEMS.ID field definitely exists.
What other reasons can cause this error?

Oracle limits the scope of a table to one level of subqueries. Here is a method that solves your problem using keep:
UPDATE DB_TEST.STOCK_ITEMS
SET STATUS = (SELECT MAX(STOCK_ITEM_STATUS) KEEP (DENSE_RANK FIRST ORDER BY CHANGED_ON DESC, ID DESC)
FROM DB_TEST.STOCK_ITEMS_HISTORY
WHERE STOCK_ITEM_ID = DB_TEST.STOCK_ITEMS.ID
)
WHERE EXISTS (SELECT 1
FROM DB_TEST.STOCK_ITEMS_HISTORY
WHERE STOCK_ITEM_ID = DB_TEST.STOCK_ITEMS.ID
);

Related

How to write DELETE Statement with Inner Query in PostgreSQL?

The below query works fine in Oracle DB.
The same query fails in Postgres DB, but the inner query works fine in Postgres DB.
DELETE FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY A.RESORT, A.RESV_NAME_ID ORDER BY ACTION_ID DESC) RNK
FROM STAGE_DETAILS A ) B
WHERE B.RNK>1;
I am getting syntax error for this.
Error :-
[Code: 0, SQL State: 42601] ERROR: syntax error at or near "(" Position: 13 [Script position: 3109 - 3110]
How to fix this ?
Thanks.
use following syntax
DELETE FROM STAGE_DETAILS A
USING (SELECT ACTION_ID,RESV_NAME_ID,ROW_NUMBER() OVER (PARTITION BY RESORT, RESV_NAME_ID ORDER BY ACTION_ID DESC) RNK
FROM STAGE_DETAILS) B
WHERE B.RNK>1 AND B.ACTION_ID = A.ACTION_ID AND B.RESV_NAME_ID = A.RESV_NAME_ID;
You cannot delete from a subquery in Postgres. This should do what you want:
DELETE FROM STAGE_DETAILS SD
WHERE ACTION_ID < (SELECT MAX(SD2.ACTION_ID)
FROM STAGE_DETAILS SD2
WHERE SD2.RESORT = SD.RESORT AND
SD2.RESV_NAME_ID = SD.RESV_NAME_ID
);

I am trying to create a table in teradata and it doesn't work

I am trying to create a table in teradata with sql, but I keep getting the following error:
CREATE TABLE FAILED. [3707] Syntax error, expected something like a name or a Unicode delimited identifier or an 'UDFCALLNAME' keyword or a 'SELECT' keyword or '(' between '(' and the 'WITH' keyword
My goal is to create a table that takes the maximum data, named "verwerkingdatum" in my code for every "contract_nr". Without the create table statement it worked just fine. Now I'm trying to create a table out of this. But I get the error above.
Here is my code:
create table mi_temp.beslagrek_saldo as
(SEL * FROM( WITH x AS
(
SELECT geld_contract_event_id, contract_nr, contract_soort_code,
contract_hergebruik_volgnr,
verwerking_datum,
event_dat,
valuta_code,
saldo_na_muteren_orig,
saldo_na_muteren_eur,
saldo_na_muteren_dc_ind,
valuta_datum,
geld_transactie_soort_code,
tegenrekening_nr,
tegenrekening_naam,
boek_datum,
storno_ind,
mutatie_bedrag_orig,
mutatie_bedrag_eur,
mutatie_bedrag_dc_ind,
soort_overboeking,
tegenrekening_nr_num,
automaat_transactie_type,
automaat_id,
automaat_datum,
automaat_tijd,
ROW_NUMBER() OVER (PARTITION BY contract_nr ORDER BY
verwerking_datum DESC) AS RowNum
FROM MI_VM_Ldm.vgeld_contract_event
WHERE verwerking_datum >= 1181201 AND verwerking_datum <= 1181231
)
SELECT geld_contract_event_id, contract_nr, contract_soort_code,
contract_hergebruik_volgnr,
verwerking_datum,
event_dat,
valuta_code,
saldo_na_muteren_orig,
saldo_na_muteren_eur,
saldo_na_muteren_dc_ind,
valuta_datum,
geld_transactie_soort_code,
tegenrekening_nr,
tegenrekening_naam,
boek_datum,
storno_ind,
mutatie_bedrag_orig,
mutatie_bedrag_eur,
mutatie_bedrag_dc_ind,
soort_overboeking,
tegenrekening_nr_num,
automaat_transactie_type,
automaat_id,
automaat_datum,
automaat_tijd
FROM X
WHERE RowNum = 1))
If I'm reading your post correctly, are you are trying to is filter your select so that your rownum = 1. You can just use qualify to accomplish that.
create table foo as (
SELECT geld_contract_event_id, contract_nr, contract_soort_code,
contract_hergebruik_volgnr,
verwerking_datum,
event_dat,
valuta_code,
saldo_na_muteren_orig,
saldo_na_muteren_eur,
saldo_na_muteren_dc_ind,
valuta_datum,
geld_transactie_soort_code,
tegenrekening_nr,
tegenrekening_naam,
boek_datum,
storno_ind,
mutatie_bedrag_orig,
mutatie_bedrag_eur,
mutatie_bedrag_dc_ind,
soort_overboeking,
tegenrekening_nr_num,
automaat_transactie_type,
automaat_id,
automaat_datum,
automaat_tijd
from
MI_VM_Ldm.vgeld_contract_event
WHERE verwerking_datum >= 1181201 AND verwerking_datum <= 1181231
qualify ROW_NUMBER() OVER (PARTITION BY contract_nr ORDER BY verwerking_datum DESC) =1
) with data;

Oracle SQL syntax error (missing right parenthesis)

I don't understand why this provokes a syntax error (missing right parenthesis):
UPDATE table
SET doc =
(SELECT 'table-2844-doc' || SUBSTR(doc_file, INSTR(doc_file, '.', -1))
FROM docvers
WHERE (docvers.table_name = 'other_table'
AND docvers.field_name = 'doc')
AND ROWNUM = 1
ORDER BY VERSION DESC)
WHERE table_id = 2844
This looks right to me, does get executed correctly in SQL Server, and is similar to requests found, for example, in Oracle SQL: Update a table with data from another table.
Any tip?
Do it like this:
UPDATE table
SET doc = (
select r.myval
from (
SELECT 'table-2844-doc' || SUBSTR(doc_file, INSTR(doc_file, '.', -1)) myval, ROWNUM RN
FROM docvers
WHERE docvers.table_name = 'other_table'
AND docvers.field_name = 'doc'
ORDER BY VERSION DESC
) r
where r.RN = 1
)
WHERE table_id = 2844
Select the data set first including the ROWNUM, then select from that data set the first row.

SQL ROW_NUMBER OVER syntax

I have this:
SELECT ROW_NUMBER() OVER (ORDER BY vwmain.ch) as RowNumber,
vwmain.vehicleref,vwmain.capid,
vwmain.manufacturer,vwmain.model,vwmain.derivative,
vwmain.isspecial,
vwmain.created,vwmain.updated,vwmain.stocklevel,
vwmain.[type],
vwmain.ch,vwmain.co2,vwmain.mpg,vwmain.term,vwmain.milespa
FROM vwMain_LATEST vwmain
INNER JOIN HomepageFeatured
on vwMain.vehicleref = homepageFeatured.vehicleref
WHERE homepagefeatured.siteskinid = 1
AND homepagefeatured.Rotator = 1
AND RowNumber = 1
ORDER BY homepagefeatured.orderby
It fails on "Invalid column name RowNumber"
Not sure how to prefix it to access it?
Thanks
You can't reference the field like that. You can however use a subquery or a common-table-expression:
Here's a subquery:
SELECT *
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY vwmain.ch) as RowNumber,
vwmain.vehicleref,vwmain.capid,
vwmain.manufacturer,vwmain.model,vwmain.derivative,
vwmain.isspecial,
vwmain.created,vwmain.updated,vwmain.stocklevel,
vwmain.[type],
vwmain.ch,vwmain.co2,vwmain.mpg,vwmain.term,vwmain.milespa,
homepagefeatured.orderby
FROM vwMain_LATEST vwmain
INNER JOIN HomepageFeatured on vwMain.vehicleref = homepageFeatured.vehicleref
WHERE homepagefeatured.siteskinid = 1
AND homepagefeatured.Rotator = 1
) T
WHERE RowNumber = 1
ORDER BY orderby
Rereading your query, since you aren't partitioning by any fields, the order by at the end is useless (it contradicts the order of the ranking function). You're probably better off using top 1...
Using top:
SELECT top 1 vwmain.vehicleref,vwmain.capid,
vwmain.manufacturer,vwmain.model,vwmain.derivative,
vwmain.isspecial,
vwmain.created,vwmain.updated,vwmain.stocklevel,
vwmain.[type],
vwmain.ch,vwmain.co2,vwmain.mpg,vwmain.term,vwmain.milespa,
homepagefeatured.orderby
FROM vwMain_LATEST vwmain
INNER JOIN HomepageFeatured on vwMain.vehicleref = homepageFeatured.vehicleref
WHERE homepagefeatured.siteskinid = 1
AND homepagefeatured.Rotator = 1
ORDER BY homepagefeatured.orderby
(EDIT: This answer is a nearby pitfall. I leave it for documentation.)
Have a look here: Referring to a Column Alias in a WHERE Clause
This is the same situation.
It is a matter of how the sql query is parsed/compiled internally, so your field alias names are not known at the time the where clause is interpreted. Therefore you might try, in reference to the example above:
SELECT ROW_NUMBER() OVER (ORDER BY vwmain.ch) as RowNumber,
vwmain.vehicleref,vwmain.capid, vwmain.manufacturer,vwmain.model,vwmain.derivative, vwmain.isspecial,vwmain.created,vwmain.updated,vwmain.stocklevel, vwmain.[type],
vwmain.ch,vwmain.co2,vwmain.mpg,vwmain.term,vwmain.milespa
FROM vwMain_LATEST vwmain
INNER JOIN HomepageFeatured on vwMain.vehicleref = homepageFeatured.vehicleref
WHERE homepagefeatured.siteskinid = 1
AND homepagefeatured.Rotator = 1
AND ROW_NUMBER() OVER (ORDER BY vwmain.ch) = 1
ORDER BY homepagefeatured.orderby
Thus you see your expression in the select statement is exactly reused in the where clause.

Over(Partition by ) Column not being recognized. Invalid column

When I execute the following query:
SELECT
MH.MemberKey,
ROW_NUMBER() OVER(PARTITION BY MH.MemberKey ORDER BY MH.MemberKey ASC) AS "NewRow",
MH.FirstName,
MH.LastName,
MH.BirthDate,
MH.AddressLine1,
MH.AddressLine2,
MH.AddressLine3,
MH.City AS MemberCity,
MH.StateCode AS MemberState,
MH.ZipCode AS MemberZip
FROM MembershipHistory MH
WHERE NewRow = 1;
I get the following error:
Msg 207, Level 16, State 1, Line 36
Invalid column name 'NewRow'.
I tried keeping AS, removing AS, removing ""....nothing seems to work. It just wont recognize the column.
The evaluation of the row_number function in the SELECT is done after the WHERE clause has been applied so the alias is not recognized, you can use a subquery to get the result:
select
MH.MemberKey,
NewRow,
MH.FirstName,
MH.LastName,
MH.BirthDate,
MH.AddressLine1,
MH.AddressLine2,
MH.AddressLine3,
MH.City AS MemberCity,
MH.StateCode AS MemberState,
MH.ZipCode AS MemberZip
from
(
SELECT
MH.MemberKey,
ROW_NUMBER() OVER(PARTITION BY MH.MemberKey ORDER BY MH.MemberKey ASC) AS NewRow,
MH.FirstName,
MH.LastName,
MH.BirthDate,
MH.AddressLine1,
MH.AddressLine2,
MH.AddressLine3,
MH.City AS MemberCity,
MH.StateCode AS MemberState,
MH.ZipCode AS MemberZip
FROM MembershipHistory MH
) MH
WHERE NewRow = 1;
In SQL Server the Logical Processinf Order of the SELECT Statement is (from MSDN Docs):
FROM
ON
JOIN
WHERE
GROUP BY
WITH CUBE or WITH ROLLUP
HAVING
SELECT
DISTINCT
ORDER BY
TOP
Another approach is to use a CTE:
;WITH x AS (SELECT MH.whatever, ROW_NUMBER() ... AS NewRow FROM dbo.table)
SELECT * FROM x WHERE NewRow = 1;