SQL - updating Oracle 10g database from a complex query - sql

trying to update a single column based on criteria. The rows that need to be updated are returned by the query
SELECT
it.objectid,
it.versionnumber,
it.itemnumber "Item Number",
it.itemtype,
itcovprem.basisofsettlement,
itcovprem.coverage "Coverage"
FROM
itemcoveragesandpremiums itcovprem,
items it,
policies pl
WHERE
pl.objectid = it.parentobjectid AND
pl.policytype in ('H','F') AND
it.objectid = itcovprem.itemobjectid AND
it.itemtype in ('SHOA','SHOB','SHOC','SHOD','SHOK','SHOL') and
it.versionnumber = itcovprem.itemversionnumber AND
((itcovprem.coverage like ('A - Dwg Bldg%')) or
(itcovprem.coverage like ('#42 - Repl Cost Plus%')) or
(itcovprem.coverage like ('#42 - Limited GRC%'))) and
it.effectivedate >= TO_DATE('01-JAN-2006', 'DD-MON-YYYY') and
exists (select * from itemcoveragesandpremiums icp where icp.itemobjectid = it.objectid and icp.itemversionnumber = it.versionnumber and icp.coverage like ('#42%')) and
itcovprem.basisofsettlement not in ('LGRC')
I've tried a few options to convert this to an update query, but no joy.
I get Error - line 3 - SQL command not properly ended when using
update itemcoveragesandpremiums
set basisofsettlement = 'LGRC'
from itemcoveragesandpremiums as itcovprem
inner join items as it
on it.objectid = itcovprem.itemobjectid and it.versionnumber = itcovprem.itemversionnumber
inner join policies as pl
on pl.objectid = it.parentobjectid
where [cut, rest of query was below]
I get Error - line 6 - missing right parenthesis when trying use an inline query
update
(
SELECT
itcovprem.basisofsettlement as OLD
FROM
itemcoveragesandpremiums as itcovprem inner join items as it on it.objectid = itcovprem.itemobjectid and it.versionnumber = itcovprem.itemversionnumber inner join policies AS pl on pl.objectid = it.parentobjectid
WHERE [query snipped]
) t
set t.old = 'LGRC'
Seems that SQL*Plus just wants to stop looking at the update before it gets to the meat of my select query. I'm not sure if I'm formatting it incorrectly or going at it from the wrong direction. Any advice?

In your first attempt, the error at line 3 is because update doesn't support a from or join clause. In your second attempt the immediate error at line 6 is because you're trying to alias a table with as itcovprem; but you can only use as for column aliases, not for table aliases. (The first attempt is trying to do that too, but it isn't getting as far as encountering that problem). But you can't generally update an inline-view with joins anyway, so it would still error with that - something like an ORA-01779.
You would need to do something like:
update itemcoveragesandpremiums
set basisofsettlement = 'LGRC'
where (itemobjectid, itemversionnumber, basisofsettlement, coverage) in (
select it.objectid,
it.versionnumber,
itcovprem.basisofsettlement,
itcovprem.coverage
from ...
)
Assuming that itemobjectid, itemversionnumber, basisofsettlement, coverage identifies a row sufficiently such that you don't risk updating anything you shouldn't. It might be safer to add a rowid to the select and use that for the update instead to avoid ambiguity:
update itemcoveragesandpremiums
set basisofsettlement = 'LGRC'
where rowid in (
select itcovprem.rowid as target_rowid
from ...
)

Related

MS Access UPDATE Query errors

I am having a hard time using MS Access because the syntax is a little finicky compared to other db's.
I am trying to validate a table and compare that table to a master table with multiple columns of information. At the moment I am trying to update a table with a field name of Difference_Value in table ct2011 to be equal to (ct2011.Distribution_Amount - AggregateFinal.SumOfDollars).
Also specifying the lines in which are going to be updated because not all rows in the MASTER are in the table ct2011.
Below is my query.
UPDATE ct2011
SET ct2011.Difference_Value = (ct2011.Distribution_Amount - AggregateFinal.SumOfDollars)
FROM
ct2011 as ct
INNER JOIN
AggregateFinal af
ON
ct.Employee_ID = af.EmpId AND ct.Legal_Name = af.LegalName AND ct.Distribution_Plan_Year = af.CalculationAwardPeriod AND ct.Award_Year = af.AwardPeriod;
I am getting a Syntax error (missing operator). It specifies that it is encountering the error during the SET expressions after the =.
In an MS Access update query, the join criteria should follow the update keyword, e.g.:
update
ct2011 ct inner join aggregatefinal af on
ct.employee_id = af.empid and
ct.legal_name = af.legalname and
ct.distribution_plan_year = af.calculationawardperiod and
ct.award_year = af.awardperiod
set
ct.difference_value = (ct.distribution_amount - af.sumofdollars)

MS Access SQL Update with Minimum

This SQL is beyond my expertise. I think it should be fairly easy for someone with experience. Here is what I have so far..
SQL is as follows:
UPDATE (Tbl_Stg_Project_Schedule_Dates
INNER JOIN Tbl_Child_ITN ON Tbl_Stg_Project_Schedule_Dates.ms_itn = Tbl_Child_ITN.ITN)
INNER JOIN Tbl_Schedule ON Tbl_Child_ITN.Id = Tbl_Schedule.ID SET Tbl_Schedule.a_construction_start = [Tbl_Stg_Project_Schedule_Dates].[ms_start_date]
WHERE (((Tbl_Stg_Project_Schedule_Dates.ms_tempt_id) In (16,17,18,19,20,21,22,23)));
I want to add one last condition to this being that I only want the minimum of [Tbl_Stg_Project_Schedule_Dates].[ms_start_date] to update the table. I've tried the obvious of wrapping the field in Min, and also tried creating a separate aggregate select statement first (to get the min value with other criteria) that I then tried to create the update query from in new query but no luck.
I believe this is valid Access/Jet SQL. The idea here is to use a subquery to look up the earliest date among all the rows in your subset. I'm not sure if ms_itn was the right column to correlate on but hopefully you get the idea:
UPDATE (Tbl_Stg_Project_Schedule_Dates
INNER JOIN Tbl_Child_ITN ON Tbl_Stg_Project_Schedule_Dates.ms_itn = Tbl_Child_ITN.ITN)
INNER JOIN Tbl_Schedule ON Tbl_Child_ITN.Id = Tbl_Schedule.ID
SET Tbl_Schedule.a_construction_start = [Tbl_Stg_Project_Schedule_Dates].[ms_start_date]
WHERE (((Tbl_Stg_Project_Schedule_Dates.ms_tempt_id) In (16,17,18,19,20,21,22,23)))
and [Tbl_Stg_Project_Schedule_Dates].[ms_start_date] = (
select min(sd.[ms_start_date])
from [Tbl_Stg_Project_Schedule_Dates] as sd
where sd.ms_itn = [Tbl_Stg_Project_Schedule_Dates].ms_itn
)

ORA-00918: column ambigously defined, using DB Link

When I execute the query below I get the following error message :
ORA-00918: column ambigously defined
ORA-02063: preceding line from ABC
Query:
SELECT
dos.*,
cmd.*,
cmd_r.*,
adr_inc.*,
adr_veh.*,
loc.*,
fou_d.*,
fou_r.*, --Works if I comment this line
mot.*
FROM
DOSSIERS#ABC dos
LEFT JOIN CMDS#ABC cmd ON cmd.DOS_CODE_ID = dos.dos_code_id
LEFT JOIN CMDS_RECCSTR#ABC cmd_r ON cmd_r.DOS_CODE_ID = dos.DOS_CODE_ID AND cmd_r.CMD_CODE_ID = cmd.CMD_CODE_ID AND cmd_r.CMD_DT_CREAT = cmd.CMD_DT_CREAT
LEFT JOIN HISTO_ADR#ABC adr_inc ON adr_inc.DOS_CODE_ID = dos.DOS_CODE_ID
LEFT JOIN HISTO_ADR#ABC adr_veh ON adr_veh.DOS_CODE_ID = dos.DOS_CODE_ID
LEFT JOIN LOC#ABC loc ON dos.DOS_CODE_ID = loc.DOS_CODE_ID
LEFT JOIN FOURNISS#ABC fou_d ON fou_d.PAY_CODE_ID = loc.PAY_CODE_ID_D AND fou_d.FOU_CODE_ID = loc.FOU_CODE_ID_D
LEFT JOIN FOURNISS#ABC fou_r ON fou_r.PAY_CODE_ID = loc.PAY_CODE_ID_R AND fou_r.FOU_CODE_ID = loc.FOU_CODE_ID_R
LEFT JOIN REF_MOT#ABC mot ON mot.RMR_CODE_ID = cmd_r.RMR_CODE_ID
WHERE
dos.REF_EXT = 'XXXXXXX'
If I comment fou_r.* in SELECT it works.
The following queries don't work neither:
SELECT *
FROM ... ;
SELECT (SELECT count(xxx) FROM ...)
FROM ...;
I looked at similar issues on SO but they were all using complex queries or was using many SELECT inside WHERE. Mine is simple that is why I don't understand what could be wrong.
Current Database: Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
Target Database (refers to db link ABC target): Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
Client: Toad for Oracle 9.7.2.5
You seem to be hitting bug 13589271. I can't share details from MOS, but there isn't much to share anyway. It's related to the remote table having a column with a 30-character name though, as you have in your remote FOURNIUSS table.
Unfortunately simply aliasing the column in your query, like this:
fou_d.COLUMN_WITH_30_CHARACTERS_NAME alias_a,
fou_r.COLUMN_WITH_30_CHARACTERS_NAME alias_b,
... doesn't help and still gets the same error, as the alias is applied by the local database and the problem seems to be during the remote access. What does seem to work is using an in-line view to apply a column alias before the join:
...
LEFT JOIN LOC#ABC loc ON dos.DOS_CODE_ID = loc.DOS_CODE_ID
LEFT JOIN (
SELECT PAY_CODE_ID, FOU_CODE_ID, COLUMN_WITH_30_CHARACTERS_NAME alias_a FROM FOURNISS#ABC
) fou_d ON fou_d.PAY_CODE_ID = loc.PAY_CODE_ID_D AND fou_d.FOU_CODE_ID = loc.FOU_CODE_ID_D
LEFT JOIN (
SELECT PAY_CODE_ID, FOU_CODE_ID, COLUMN_WITH_30_CHARACTERS_NAME alias_b FROM FOURNISS#ABC
) fou_r ON fou_r.PAY_CODE_ID = loc.PAY_CODE_ID_R AND fou_r.FOU_CODE_ID = loc.FOU_CODE_ID_R
LEFT JOIN REF_MOT#ABC mot ON mot.RMR_CODE_ID = cmd_r.RMR_CODE_ID
...
This even works if you give the column the same alias in both inline views. The downside is that you have to explicitly list all of the columns from the table (or at least those you're interested in) in order to be able to apply the alias to the problematic one, but having done so you can still use fou_d.* and fou_r.* in the outer select list.
I don't have an 11.2.0.2 database but I've run this successfully in an 11.2.0.3 database which still showed the ORA-00918 error from your original code. It's possible something else in 11.2.0.2 will stop this workaround being effective, of course. I don't see the original problem in 11.2.0.4 at all, so upgrading to that terminal patch release might be a better long-term solution.
Using * is generally considered a bad practice anyway though, not least because you're going to get a lot of duplicated columns from the joins (lots of dos_code_id in each row, for example); but you're also likely to be getting other data you don't really want, and anything that consumes this result set will have to assume the column order is always the same in those tables - any variation, or later addition or removal of a column, will cause problems.

Syntax Error - Missing Operator - Cannot determine what is missing

What is wrong with the SQL statement? I get a message that there is a syntax error (missing operator). From the ASSIGNMENT TABLE I am wanting to select all rows where ASSN_TRANS_STATE_NUM = '1'. For each of these rows I then want to get the project name from the PROJECTS table. I also want to get each of the Task names from the TASKS table. I did get this to work earlier (not sure what change I made that broke it) but even when it did work it was not correct. It was reporting every task for each of the projects, instead of just giving me the tasks specific to a project.
SELECT
TRANS.PROJ_UID,
PROJ.PROJ_NAME,
TRANS.TASK_UID,
TASKS.TASK_NAME,
TRANS.ASSN_TRANS_STATE_ENUM,
TRANS.ASSN_TRANS_APPROVER_RES_UID
FROM dbo_MSP_ASSIGNMENT_TRANSACTIONS TRANS
INNER JOIN dbo_MSP_PROJECTS PROJ ON PROJ.PROJ_UID = TRANS.PROJ_UID
INNER JOIN dbo_MSP_TASKS TASKS ON TASKS.TASK_UID = TRANS.TASK_UID
WHERE TRANS.ASSN_TRANS_STATE_ENUM = 1;
It will be dbo. rather than dbo_. I guess it should help
SELECT
TRANS.PROJ_UID,
PROJ.PROJ_NAME,
TRANS.TASK_UID,
TASKS.TASK_NAME,
TRANS.ASSN_TRANS_STATE_ENUM,
TRANS.ASSN_TRANS_APPROVER_RES_UID
FROM dbo.MSP_ASSIGNMENT_TRANSACTIONS TRANS
INNER JOIN dbo.MSP_PROJECTS PROJ ON PROJ.PROJ_UID = TRANS.PROJ_UID
INNER JOIN dbo.MSP_TASKS TASKS ON TASKS.TASK_UID = TRANS.TASK_UID
WHERE TRANS.ASSN_TRANS_STATE_ENUM = 1;

Whats wrong with this nested query?

I am trying to write a query to return the id of the latest version of a market index stored in a database.
SELECT miv.market_index_id market_index_id from ref_market_index_version miv
INNER JOIN ref_market_index mi ON miv.market_index_id = mi.id
WHERE mi.short_name='dow30'
AND miv.version_num = (SELECT MAX(m1.version_num) FROM ref_market_index_version m1 INNER JOIN ref_market_index m2 ON m1.market_index_id = m2.id )
The above SQL statement can be (roughly) translated into the form:
SELECT some columns FROM SOME CRITERIA MATCHED TABLES
WHERE mi.short_name='some name'
AND miv.version_num = SOME NUMBER
What I don't understand is that when I supply an actual number (instead of a sub query), the SQL statement works - also, when I test the SUB query used to determine the latest version number, that also works - however, when I attempt to use the result returned by sub query in the outer (parent?) query, it returns 0 rows - what am I doing wrong here?
Incidentally, I also tried an IN CLAUSE instead of the strict equality match i.e.
... AND miv.version_num IN (SUB QUERY)
That also resulted in 0 rows, although as before, when running the parent query with a hard coded version number, I get 1 row returned (as expected).
BTW I am using postgeresql, but I prefer the solution to be db agnostic.
The problem is probably that the max(version_num) doesn't exist for 'dow30'.
Try the following correlated subquery:
SELECT miv.market_index_id market_index_id
from ref_market_index_version miv INNER JOIN
ref_market_index mi
ON miv.market_index_id = mi.id
WHERE mi.short_name='dow30' AND
miv.version_num = (SELECT MAX(m1.version_num)
FROM ref_market_index_version m1 INNER JOIN
ref_market_index m2
ON m1.market_index_id = m2.id
where m1.short_name = 'dow30'
)
I added the where clause in the subquery.