MS Access query: Use a select statement within Switch() function - sql

I am using switch() function for a conditional Update in MS Access query. Below is my query
UPDATE T_Generated_OpportunityLine SET PlContact_c = Switch(
LowestlevelValue_c='PTFDS - FD ENCLOSURE SYSTEMS',Select OpportunityLine_PostCode.SESA from OpportunityLine_PostCode,T_Generated_OpportunityLine where OpportunityLine_PostCode.Postcode=T_Generated_OpportunityLine.Selected_Zip AND
OpportunityLine_PostCode.OpptyLine_Ref='PTFDS',
LowestlevelValue_c='DOOR ENTRY SYSTEM',Select OpportunityLine_PostCode.SESA from OpportunityLine_PostCode,T_Generated_OpportunityLine where OpportunityLine_PostCode.Postcode=T_Generated_OpportunityLine.Selected_Zip AND
OpportunityLine_PostCode.OpptyLine_Ref='Door Entry System'
);
I am aware with the syntax of switch() function:
Switch ( expression1, value1, expression2, value2, ... expression_n, value_n )
I have just made one modification i.e. instead of passing Static value for "Value" section I am fetching this value Dynamically through Select Query.
But when I am trying to execute the query Its stating an error message that:
The query must be an updatable query
I am sure that problem is for Select Statement inside Switch() function,but I need this conditional update on account of my project.
Can anyone provide any suitable solution to this? I also want to know can we pass dynamic value for "Value" Portion in Switch() syntax?

I don't know if this is your problem, but normally subqueries need to be enclosed in parentheses:
UPDATE T_Generated_OpportunityLine
SET PlContact_c = Switch(LowestlevelValue_c='PTFDS - FD ENCLOSURE SYSTEMS',
(Select SESA
from OpportunityLine_PostCode
where OpportunityLine_PostCode.Postcode = T_Generated_OpportunityLine.Selected_Zip AND
OpportunityLine_PostCode.OpptyLine_Ref = 'PTFDS'
),
LowestlevelValue_c = 'DOOR ENTRY SYSTEM',
(Select SESA
from OpportunityLine_PostCode
where OpportunityLine_PostCode.Postcode = T_Generated_OpportunityLine.Selected_Zip AND
OpportunityLine_PostCode.OpptyLine_Ref='Door Entry System'
));
However, I would write this with just one subquery:
UPDATE T_Generated_OpportunityLine
SET PlContact_c = (Select SESA
from OpportunityLine_PostCode as pc
where pc.Postcode = T_Generated_OpportunityLine.Selected_Zip AND
(T_Generated_OpportunityLine.LowestlevelValue_c = 'PTFDS - FD ENCLOSURE SYSTEMS' AND pc.OpptyLine_Ref = 'PTFDS' OR
T_Generated_OpportunityLine.LowestlevelValue_c = 'DOOR ENTRY SYSTEM' AND op.OpptyLine_Ref='Door Entry System'
)
);

Related

How to write an Open SQL statement with substring in the JOIN ON condition? [duplicate]

I have the following select statement in ABAP:
SELECT munic~mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE_M ZZONE_T USAGE_M USAGE_T M2MC M2MT M2RET EXEMPTMCMT EXEMPRET CHARGEMCMT
INTO corresponding fields of table GT_INSTMUNIC_F
FROM ZCI00_INSTMUNIC AS MUNIC
INNER JOIN EVER AS EV on
MUNIC~POD = EV~VREFER(9).
"where EV~BSTATUS = '14' or EV~BSTATUS = '32'.
My problem with the above statement is that does not recognize the substring/offset operation on the 'ON' clause. If i remove the '(9) then
it recognizes the field, otherwise it gives error:
Field ev~refer is unknown. It is neither in one of the specified tables
nor defined by a "DATA" statement. I have also tried doing something similar in the 'Where' clause, receiving a similar error:
LOOP AT gt_instmunic.
clear wa_gt_instmunic_f.
wa_gt_instmunic_f-mandt = gt_instmunic-mandt.
wa_gt_instmunic_f-bis = gt_instmunic-bis.
wa_gt_instmunic_f-ab = gt_instmunic-ab.
wa_gt_instmunic_f-zzelecdate = gt_instmunic-zzelecdate.
wa_gt_instmunic_f-ZZCERTDATE = gt_instmunic-ZZCERTDATE.
wa_gt_instmunic_f-CONSYEAR = gt_instmunic-CONSYEAR.
wa_gt_instmunic_f-ZDIMO = gt_instmunic-ZDIMO.
wa_gt_instmunic_f-ZZONE_M = gt_instmunic-ZZONE_M.
wa_gt_instmunic_f-ZZONE_T = gt_instmunic-ZZONE_T.
wa_gt_instmunic_f-USAGE_M = gt_instmunic-USAGE_M.
wa_gt_instmunic_f-USAGE_T = gt_instmunic-USAGE_T.
temp_pod = gt_instmunic-pod.
SELECT vrefer
FROM ever
INTO wa_gt_instmunic_f-vrefer
WHERE ( vrefer(9) LIKE temp_pod ). " PROBLEM WITH SUBSTRING
"AND ( BSTATUS = '14' OR BSTATUS = '32' ).
ENDSELECT.
WRITE: / sy-dbcnt.
WRITE: / 'wa is: ', wa_gt_instmunic_f.
WRITE: / 'wa-ever is: ', wa_gt_instmunic_f-vrefer.
APPEND wa_gt_instmunic_f TO gt_instmunic_f.
WRITE: / wa_gt_instmunic_f-vrefer.
ENDLOOP.
itab_size = lines( gt_instmunic_f ).
WRITE: / 'Internal table populated with', itab_size, ' lines'.
The basic task i want to implement is to modify a specific field on one table,
pulling values from another. They have a common field ( pod = vrefer(9) ). Thanks in advance for your time.
If you are on a late enough NetWeaver version, it works on 7.51, you can use the OpenSQL function LEFT or SUBSTRING. Your query would look something like:
SELECT munic~mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE_M ZZONE_T USAGE_M USAGE_T M2MC M2MT M2RET EXEMPTMCMT EXEMPRET CHARGEMCMT
FROM ZCI00_INSTMUNIC AS MUNIC
INNER JOIN ever AS ev
ON MUNIC~POD EQ LEFT( EV~VREFER, 9 )
INTO corresponding fields of table GT_INSTMUNIC_F.
Note that the INTO clause needs to move to the end of the command as well.
field(9) is a subset operation that is processed by the ABAP environment and can not be translated into a database-level SQL statement (at least not at the moment, but I'd be surprised if it ever will be). Your best bet is either to select the datasets separately and merge them manually (if both are approximately equally large) or pre-select one and use a FAE/IN clause.
They have a common field ( pod = vrefer(9) )
This is a wrong assumption, because they both are not fields, but a field an other thing.
If you really need to do that task through SQL, I'll suggest you to check native SQL sentences like SUBSTRING and check if you can manage to use them within an EXEC_SQL or (better) the CL_SQL* classes.

SELECT instead of TABLE and WHERE in UPDATE?

I've seen may answers to the same kind of question but I still doubt.
UPDATE in SQL should be something like :
UPDATE *Table*
SET *choose value*
WHERE *what do we change*
I would like to know if there is possibilites to use a select instead of TABLE (an so instead of WHERE)
Like
UPDATE *Select conditions and rows*
SET *What do we change (the where is implicit)
I know UPDATE/SET/WHERE works well, but I'm exploring other possibilites :)
Thanks,
Nicolas
EXAMPLE :
Have to do :
update produits
set `NO_FOURNISSEUR` = "30"
where `NO_FOURNISSEUR` = "3"
would like to try something like :
update select * from produits where produits.`no_fournisseur`= "30"
set `NO_FOURNISSEUR`= "3"
MariaDB has a with expression, like so:
https://mariadb.com/kb/en/library/with/
so you would have:
WITH t AS (
select *
from produits
where produits.no_fournisseur= '30')
UPDATE t SET t.no_fournisseur = '3';
Yes. The ANSI SQL standard way to do this is using a Common Table Expression:
with dt as
(
select *
from produits
where produits.no_fournisseur= '30'
)
update dt set NO_FOURNISSEUR = '3'
This standard syntax supports joins and other query constructs in the SELECT part, and gives you a simple way to examine the rows before applying the update.

ORA-38104 when trying to update my table using merge

I have a stored procedure in which I want to update some columns, so I wrote below code:
PROCEDURE UPDATE_MST_INFO_BKC (
P_SAPID IN NVARCHAR2
) AS
BEGIN
MERGE INTO tbl_ipcolo_billing_mst I
USING (
SELECT
R4G_STATE, -- poilitical state name
R4G_STATECODE, -- poilitical state code
CIRCLE, -- city name
NE_ID,
LATITUDE,
LONGITUDE,
SAP_ID
FROM
R4G_OSP.ENODEB
WHERE
SAP_ID = P_SAPID
AND ROWNUM = 1
)
O ON ( I.SAP_ID = O.SAP_ID )
WHEN MATCHED THEN
UPDATE SET I.POLITICAL_STATE_NAME = O.R4G_STATE,
I.POLITICAL_STATE_CODE = O.R4G_STATECODE,
I.CITY_NAME = O.CIRCLE,
I.NEID = O.NE_ID,
I.FACILITY_LATITUDE = O.LATITUDE,
I.FACILITY_LONGITUDE = O.LONGITUDE,
I.SAP_ID = O.SAP_ID;
END UPDATE_MST_INFO_BKC;
But it is giving me error as
ORA-38104: Columns referenced in the ON Clause cannot be updated: "I"."SAP_ID"
What am I doing wrong?
You are joining the source to destination tables on I.SAP_ID = O.SAP_ID and then, when matched, are trying to update them and set I.SAP_ID = O.SAP_ID. You cannot update the columns used in the join ... and why would you want to as you have already determined that the values are equal.
Just remove the last line of the UPDATE:
...
O ON ( I.SAP_ID = O.SAP_ID )
WHEN MATCHED THEN
UPDATE SET I.POLITICAL_STATE_NAME = O.R4G_STATE,
I.POLITICAL_STATE_CODE = O.R4G_STATECODE,
I.CITY_NAME = O.CIRCLE,
I.NEID = O.NE_ID,
I.FACILITY_LATITUDE = O.LATITUDE,
I.FACILITY_LONGITUDE = O.LONGITUDE;
The error message tells you what the problem is - a MERGE statement cannot update the columns used in the ON clause - and even tells you what column is the problem: "I"."SAP_ID".
So Oracle hurls ORA-38104 because of this line in your WHEN MATCHED branch
I.SAP_ID = O.SAP_ID;
Remove it and your problem disappears. Fortunately the line is unnecessary: I.SAP_ID already equals O.SAP_ID, otherwise the record wouldn't go down the MATCHED branch.
The reason why is quite straightforward: transactional consistency. The MERGE statement operates over a set of records defined by the USING clause and the ON clause. Updating the columns used in the ON clause threatens the integrity of that set, and so Oracle forbids it.

How to give change working of having function dynamicaly on executing an sql statement?

I'm having a Sql code like as follows
Select a.ItemCode, a.ItemDesc
From fn_BOM_Material_Master('A', #AsOnDate, #RptDate, #BranchID, #CompID)a
Left Outer Join fn_INV_AsOnDate_Stock(#StockDate, #AsOnDate, #RptDate, #BranchID, #CompID, #Finyear)b
On a.ItemCode=b.ItemCode and b.WarehouseCode<>'WAP'
and a.BranchID=b.BranchID and a.CompID=b.COmpID
Where a.ItemNatureCode = 'F' and a.BranchID = #BranchID and a.CompID = #CompID
Group by a.ItemCode, a.ItemDesc
Having sum(b.CBQty)<=0
Here the problem is that im passing an "#ShowZeroStock" value as as bit if the "#ShowZeroStock" value is '1' then Having should not be validated or (i.e: All values from the table should be returned including zero)
So How to change the query based on passed bit value "#ShowZeroStock"
I can Use "If else " condition at the top and remove having in else part, but for a lengthy query i can't do the same.
Is this the logic you want?
Having sum(b.CBQty) <= 0 or #ShowZeroStock = 1

sql select with one value of two where

This is the only place that I get all answer ;)
I want to select :
SELECT
RTRIM(LTRIM(il.Num_bloc)) AS Bloc,
RTRIM(LTRIM(il.num_colis)) AS Colis,
cd.transporteur AS Coursier,
cd.origine AS Origine,
cd.destination AS Destinataire,
cd.adresse AS [Adresse Destinataire],
cd.poids AS Poids,
il.Signataire, il.num_cin AS CIN, il.date_livraison AS [Date Livraison]
FROM
dbo.cd
INNER JOIN
dbo.il ON cd.bloc = il.Num_bloc AND dbo.cd.colis = dbo.il.num_colis
WHERE
(il.Num_bloc = RTRIM(LTRIM(#ParamBloc)))
AND (il.num_colis = RTRIM(LTRIM(#ParamColis)))
In the way of getting result if the user put ether #ParamBloc or #ParamColis
Try using IsNull() function.
A simple query would go like this
Select * from yourTable
Where
Num_bloc = ISNULL(#ParamBloc, Num_block) AND
num_colis = ISNULL(#ParamColis, num_colis)
The second parameter would make the expression to true if the #parameter Bloc or Colis is null. This query would be useful for all 4 possible combination of these two parameter.