SQL can not refer table in from clause within where - sql

I have a simple SQL query used in oracle 11g
select something
from sc
where sc.column satisfies something
but I can not refer SC in the where composite, any one can help explain this, thanks in advance.
---second edit: I tested the sql command in oracle 19c it works but in 11g it does not work.
table contents
create table sc(
sno varchar2(10),
cno varchar2(10),
score number(4,2),
constraint pk_sc primary key (sno,cno)
);
example data
insert into sc values ('s001','c001',78.9);
insert into sc values ('s002','c001',80.9);
insert into sc values ('s003','c001',81.9);
insert into sc values ('s004','c001',60.9);
insert into sc values ('s001','c002',82.9);
insert into sc values ('s002','c002',72.9);
insert into sc values ('s003','c002',81.9);
insert into sc values ('s001','c003','59');
sql command
SELECT SNO
FROM SC A
WHERE 0 = (SELECT COUNT(*)
FROM
(SELECT B.CNO
FROM SC B
WHERE B.SNO = 's001'
MINUS
SELECT C.CNO
FROM SC C
WHERE A.SNO = C.SNO) --this is the error location, oracle reports invalid identifier A.
);

I would try a exists clause instead of where 0 =
SELECT SNO
FROM SC A
WHERE not exists (SELECT B.CNO
FROM SC B
WHERE B.SNO = 's001'
MINUS
SELECT C.CNO
FROM SC C
WHERE A.SNO = C.SNO) --this is the error location, oracle reports undefined A.
I'm assuming you want to return where there is not a match?

If you're trying to get the CNO that are not only in SNO 's001'.
Then maybe this.
SELECT DISTINCT SNO, cno
FROM SC sc
WHERE SNO = 's001'
AND EXISTS (
SELECT 1
FROM SC sc2
WHERE sc2.CNO = sc.CNO
AND sc2.SNO != sc.SNO
)

Related

Increase number into insert from select in SQL

In the code there is a lot of rows will be inserted and the code gives me this error
[23000][2601] Cannot insert duplicate key row in object 'dbo.Estimates' with unique index 'IX_Estimates_EstimateNumber'. The duplicate key value is (10005)
Code:
INSERT INTO dbo.Estimates (EstimateNumber, Date, Comments, CustomerId)
SELECT
(SELECT MAX(Number) + 1 FROM EstimateNumber),
po.DateReceived,
po.Notes,
(SELECT Id FROM Customers WHERE Name = po.Customer)
FROM
staging.PricingTable po
LEFT JOIN
dbo.Estimates Es ON Es.Date = po.DateReceived
WHERE
Es.Date IS NULL;
The issue is happening because select MAX(Number)+1 FROM EstimateNumber in the select clause will not work as you expect and always return the same value for each row. Since there is an unique index, it will block the data insert. You can execute the select statement to verify this.
You can use a ROW_NUMBER() to fix this.
A sample sql code is follows :
declare #maxval integer ;
select #maxval = max(Number) from EstimateNumber ;
insert into dbo.Estimates ( EstimateNumber, Date,Comments, CustomerId )
select #maxval + ROW_NUMBER() OVER (ORDER BY c.Id), po.DateReceived, po.Notes, c.Id
from staging.PricingTable po
join Customers c on c.Name = po.Customer
left join dbo.Estimates Es on Es.Date = po.DateReceived
where Es.Date is null;
here I have used a local variable to hold max(Number) and incremenetd it using row_number. also moved the Cutomers from nested-select to a join

how can insert sql server stored procedure data to the new table?

I have following sql server stored procedure
SELECT
APO_Order_Id as Purchase_Order_Number,
CompanyID as Company_ID,
p.PJM_UserDefinedProjID as Project_ID,
case m.APO_Use_Alt_Address
end as Project_Site_Address, p.PJM_StartDate as Site_StartDate,
s.CNT_ClientName as Creditor,s.CNT_ABN as Creditor_ABN,s.CNT_UID as Creditor_Id,s.CNT_CreditorType as Creditor_Type, m.APO_Description as Purchase_Order_Description, isnull(d.Order_Amount,0) as Order_Total
FROM
Account_APOrderMaster m
left join
(
SELECT
APOD_Master_Id, APOD_Project_Id, sum(APOD_Total_Amount) as Order_Amount
FROM
Account_APOrderDetail
group by
APOD_Master_Id, APOD_Project_Id
) d on m.Ref_Code = d.APOD_Master_Id
left join Client_Name s on m.APO_Supplier_ID = s.Ref_Code
left join Project_Master p on d.APOD_Project_Id = p.ref_code
left join Client_Name pm on m.APO_ProjectManagerId = pm.Ref_Code
WHERE
apo_order_id = 00122975;
now I need insert data values of CompanyId to the table 'InvoiceMaster'. how can I insert CompanyID to the table?
If you have access to alter the stored procedure you can write insert command top of your query at procedure
INSERT INTO InvoiceMaster(Name of your column)
SELECT
CompanyID as Company_ID
FROM
Account_APOrderMaster m
LEFT JOIN
(SELECT
APOD_Master_Id, APOD_Project_Id,
SUM(APOD_Total_Amount) AS Order_Amount
FROM
Account_APOrderDetail
GROUP BY
APOD_Master_Id, APOD_Project_Id) d ON m.Ref_Code = d.APOD_Master_Id
LEFT JOIN
Client_Name s ON m.APO_Supplier_ID = s.Ref_Code
LEFT JOIN
Project_Master p ON d.APOD_Project_Id = p.ref_code
LEFT JOIN
Client_Name pm ON m.APO_ProjectManagerId = pm.Ref_Code
WHERE
apo_order_id = 00122975;
If you can't access the stored procedure code, it's better to write function for solve problems.
If you can't do that you should use ad-hoc distributed queries option in SQL Server
insert output of stored procedure in temp table
Or this link for solve your problems
insert stored procedure output to temp table

Error while using same table data twice during inner join

Suppose I have a table, in Database name 'Old', as below:
TABLE A
(
SeniorVehicle varchar(255),
SeniorVehicleAllowance int,
JuniorVehicle varchar(255),
JuniorVehicleAllowance int
ManagerVehicle varchar(255),
ManagerVehicleAllowance int
);
And another table, in Database name 'New' as below:
TABLE B
(
SeniorVehicle int,
SeniorVehicleAllowance int,
JuniorVehicle int,
JuniorVehicleAllowance int,
ManagerVehicle int,
ManagerVehicleAllowance int
);
I want to bring the data from TABLE A of Database 'Old' to TABLE B of Database 'New'.
The thing is that, there is a table named Vehicle in both databases as bellow:
TABLE Vehicle
(
VehicleID int pk,
VehicleName varchar(255)
)
Values in SeniorVehicle, JuniorVehicle and ManagerVehicle columns in TABLE A are the VehicleName value in TABLE Vehicle. But the value of SeniorVehicle, JuniorVehicle and ManagerVehicle that must be stored in TABLE B must be the value of VehicleID column in the Vehicle Table.
How to achieve this without error????
I have tried the following:
INSERT INTO B
(SeniorVehicle, SeniorVehicleAllowance, JuniorVehicle, JuniorniorVehicleAllowance, ManagerVehicle, ManagerVehicleAllowance)
SELECT Vehicle.VehicleID, c.SeniorVehicleAllowance, c.VehicleID, c.JuniorVehicleAllowance, c.VehicleID, c.ManagerVehicleAllowance
FROM (SELECT b.SeniorVehicle, b.SeniorVehicleAllowance, Vehicle.VehicleID, b.JuniorVehicleAllowance, b.VehicleID, b.ManagerVehicleAllowance
FROM (SELECT a.SeniorVehicle, a.SeniorVehicleAllowance, a.JuniorVehicle, a.JuniorVehicleAllowance, Vehicle.VehicleID, a.ManagerVehicleAllowance
FROM (SELECT SeniorVehicle, SeniorVehicleAllowance, JuniorVehicle, JuniorVehicleAllowance, ManagerVehicle, ManagerVehicleAllowance FROM A) as a
Inner join
Vehicle
ON a.ManagerVehicle = Vehicle.VehicleName) as b
Inner join
Vehicle
ON b.JuniorVehicle = Vehicle.VehicleName) as c
Inner join
Vehicle
ON c.SeniorVehicle = Vehicle.VehicleName
I get the following error:
The column 'VehicleID' was specified multiple times for 'c'
My Databse is MSSQL Server 2008 R2
Reformatting your current query gives:
SELECT
Vehicle.VehicleID,
c.SeniorVehicleAllowance,
c.VehicleID,
c.JuniorVehicleAllowance,
c.VehicleID,
c.ManagerVehicleAllowance
FROM (
SELECT b.SeniorVehicle,
b.SeniorVehicleAllowance,
Vehicle.VehicleID,
b.JuniorVehicleAllowance,
b.VehicleID,
b.ManagerVehicleAllowance
FROM (
SELECT a.SeniorVehicle,
a.SeniorVehicleAllowance,
a.JuniorVehicle,
a.JuniorVehicleAllowance,
Vehicle.VehicleID,
a.ManagerVehicleAllowance
FROM (
SELECT SeniorVehicle,
SeniorVehicleAllowance,
JuniorVehicle,
JuniorVehicleAllowance,
ManagerVehicle,
ManagerVehicleAllowance
FROM A
) as a
Inner join Vehicle
ON a.ManagerVehicle = Vehicle.VehicleName
) as b
Inner join Vehicle
ON b.JuniorVehicle = Vehicle.VehicleName
) as c
Inner join Vehicle
ON c.SeniorVehicle = Vehicle.VehicleName
In this query, the sub query aliased c has two columns called VehicleID (which is what your error message is telling you.
The smallest change to fix the issue is to alias the columns in the sub query, e.g:
SELECT
Vehicle.VehicleID AS SeniorVehicleId,
c.SeniorVehicleAllowance,
c.JuniorVehicleId,
c.JuniorVehicleAllowance,
c.ManagerVehicleID,
c.ManagerVehicleAllowance
FROM (
SELECT b.SeniorVehicle,
b.SeniorVehicleAllowance,
Vehicle.VehicleID AS JuniorVehicleId,
b.JuniorVehicleAllowance,
b.ManagerVehicleID,
b.ManagerVehicleAllowance
FROM (
SELECT a.SeniorVehicle,
a.SeniorVehicleAllowance,
a.JuniorVehicle,
a.JuniorVehicleAllowance,
Vehicle.VehicleID AS ManagerVehicleID,
a.ManagerVehicleAllowance
-- Rest ommited for brevity
It would be also possible to re-write the query with more joins, and omit the need for the subqueries altogether also:
SELECT srmgr.VehicleId AS SeniorVehicleId,
A.SeniorVehicleAllowance,
jrmgr.VehicleId AS JuniorVehicleId,
A.JuniorVehicleAllowance,
mgr.VehicleId AS ManagerVehicleId,
A.ManagerVehicleAllowance
FROM A
INNER JOIN Vehicle AS mgr
ON a.ManagerVehicle = mgr.VehicleName
INNER JOIN Vehicle AS jrmgr
ON a.ManagerVehicle = jrmgr.VehicleName
INNER JOIN Vehicle AS srmgr
ON a.ManagerVehicle = srmgr.VehicleName

Inserting Column From Into Another Table Trough Query

How do I update the Range field of of this table below
(don't mind the '1' values from the range above, it's supposed to be NULL)
with the Range values of this table below
When I inner join the table with the other on their EquipmentCode the values are doubled like this:
This was the query I used:
SELECT
C.*,
R.Range AS RangeFromOtherTable
FROM
EquipmentCalibrationRef AS C
INNER JOIN
Range AS R
ON
R.EquipmentCode = C.EquipmentCode
As a start, you can use following statement to get a pseudo 1 to 1 match
SELECT ecr.*, r.[Range]
FROM EquipmentCalibrationRef ecr
INNER JOIN (
SELECT RefNo = ROW_NUMBER() OVER (PARTITION BY EquipmentCode ORDER BY [Range]), *
FROM [Range] r
) r ON r.RefNo = ecr.RefNo AND r.EquipmentCode = c.EquipmentCode

Update multiple table column values using single query

How would you update data in multiple tables using a single query?
MySQL Example
The equivalent code in MySQL:
UPDATE party p
LEFT JOIN party_name n ON p.party_id = n.party_id
LEFT JOIN party_details d ON p.party_id = d.party_id
LEFT JOIN incident_participant ip ON ip.party_id = p.party_id
LEFT JOIN incident i ON ip.incident_id = i.incident_id
SET
p.employee_id = NULL,
c.em_address = 'x#x.org',
c.ad_postal = 'x',
n.first_name = 'x',
n.last_name = 'x'
WHERE
i.confidential_dt IS NOT NULL
What would be the same statement using Oracle 11g?
Thank you!
RTFM
It seems a single query is insufficient when using Oracle:
http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96540/statements_108a.htm#2067717
/** XXX CODING HORROR... */
Depending on your needs, you could use an updateable view. You create a view of your base tables and add an "instead of" trigger to this view and you update the view directly.
Some example tables:
create table party (
party_id integer,
employee_id integer
);
create table party_name (
party_id integer,
first_name varchar2(120 char),
last_name varchar2(120 char)
);
insert into party values (1,1000);
insert into party values (2,2000);
insert into party values (3,3000);
insert into party_name values (1,'Kipper','Family');
insert into party_name values (2,'Biff','Family');
insert into party_name values (3,'Chip','Family');
commit;
select * from party_v;
PARTY_ID EMPLOYEE_ID FIRST_NAME LAST_NAME
1 1000 Kipper Family
2 2000 Biff Family
3 3000 Chip Family
... then create an updateable view
create or replace view party_v
as
select
p.party_id,
p.employee_id,
n.first_name,
n.last_name
from
party p left join party_name n on p.party_id = n.party_id;
create or replace trigger trg_party_update
instead of update on party_v
for each row
declare
begin
--
update party
set
party_id = :new.party_id,
employee_id = :new.employee_id
where
party_id = :old.party_id;
--
update party_name
set
party_id = :new.party_id,
first_name = :new.first_name,
last_name = :new.last_name
where
party_id = :old.party_id;
--
end;
/
You can now update the view directly...
update party_v
set
employee_id = 42,
last_name = 'Oxford'
where
party_id = 1;
select * from party_v;
PARTY_ID EMPLOYEE_ID FIRST_NAME LAST_NAME
1 42 Kipper Oxford
2 2000 Biff Family
3 3000 Chip Family
I was having the same problem I couldn't find a easy way to do this in Oracle.
Look here:
Oracle Update Statements for more info.
You could use Oracle MERGE statement to do this. It is a bulk update-or-insert kind of statement based on joining the target table with an inline view.
MERGE INTO bonuses D
USING (
SELECT employee_id, salary, department_id FROM employees
WHERE department_id = 80
) S ON (D.employee_id = S.employee_id)
WHEN MATCHED THEN
UPDATE SET D.bonus = D.bonus + S.salary*.01
WHEN NOT MATCHED THEN
INSERT (D.employee_id, D.bonus)
VALUES (S.employee_id, S.salary*0.1);
if you do not need the insert part, you just omit the last 3 lines above.
In some cases it's possible to use PL/SQL to achieve this. In my case I searched for matching rows in two tables by some criteria, then updated each row in a loop.
Something like this:
begin
for r in (
select t1.id as t1_id, t2.id as t2_id
from t1, t2
where ...
) loop
update t1
set ...
where t1.id = r.t1_id;
update t2
set ...
where t2.id = r.t2_id;
end loop;
end;