PL/SQL : Example for select and update the record based on certain rule - oracle

I have situation something like below...
select * from tableA A
if A.salary > 100 and A.years > 0 then
update tableA set A.level = '1' where A.id = id;
else if A.salary > 200 A.years > 1 then
update tableA set A.level = '2' where A.id = id;
else
update tableA set A.level = '0' where A.id = id;
end if
how i can implement this in PL/SQL? above situation is just an example.

You don't need to do this in PL/SQL; it can be done in a single UPDATE statement by using a CASE expression:
update tablea
set level = case when salary > 100 and years > 0 then 1
when salary > 200 and years > 1 then 2
else 0
end
It's worth noting that "level" is a reserved word (it's a psuedocolumn used for Oracle's hierarchical queries) and can cause problems if you use it. I'd choose something else if possible.

Related

ora-00933 : oracle update query using join sql command not properly ended

I have a query , when I run the below query in Oracle
update cust_logs el
set batch_id = '3344'
from
client c
join port p on p.pid = c.pid
and
p.flag = 0
where
c.cid = el.cid
and
c.flag = 0
and
p.export = 1
and
el.trans_id is nul
I am getting error as
ORA-00933: sql command not properly ended.
I have tried
merge into cust_logs el
using (
select *
from client c
join port p
on (
p.pid = c.pid
and p.flag = 0
)
) "s"
on ((
c.cid = el.cid
and c.flag = 0
and p.export = 1
and decode(el.trans_id, nul, 1, 0) = 1
))
when matched then update set
batch_id = '3344'
Can you please let me know how to resolve
This is my sql fiddle
http://sqlfiddle.com/#!4/c9166/1
You can't join in an update.
You haven't said what the issue is with your merge attempt. But your on clause referring to the base table instead of the "s" alias. And the select * will cause an ambiguous identifier error as pid appears in both tables. And it's null not nul.
So this might be closer, at least:
merge into cust_logs el
using (
select c.cid, c.flag, p.export
from client c
join port p
on p.pid = c.pid
where p.flag = 0
) s
on (
s.cid = el.cid
and s.flag = 0
and s.export = 1
and decode(el.trans_id, null, 1, 0) = 1
)
when matched then update set batch_id = '3344'
But we don't have your tables or data to verify it.
If batch_id is a numeric column then the last line should be:
when matched then update set batch_id = 3344

Unexpected NULL in multi-column correlated update

I want to run a multi-column correlated update of this kind:
UPDATE t1 t1_alias
SET (table_name, tablespace_name) = (
SELECT table_name, tablespace_name
FROM t2 t2_alias
WHERE t1_alias.table_name = t2_alias.table_name
);
But my attempt:
update customer up
set (customer_name, account, active) = (
select tmp.name, tmp.account, case when tmp.active = 'Yes' then 1 else 0 end
from customer_temp tmp
where up.agent = substr(tmp.agent, -4) and up.customer_code = tmp.code
);
... throws:
ORA-01407: cannot update ("FOO"."CUSTOMER"."CUSTOMER_NAME") to NULL
The source table customer_temp has no null values so I must be getting matches wrong. What is my error or misconception?
Presumably, there are some rows in the target table that have no match in the subquery.
You can avoid this with by adding an exists condition that filters out "unmatched" rows:
update customer up
set (customer_name, account, active) = (
select tmp.name, tmp.account, case when tmp.active = 'Yes' then 1 else 0 end
from customer_temp tmp
where up.agent = substr(tmp.agent, -4) and up.customer_code = tmp.code
)
where exists (
select 1
from customer_temp tmp
where up.agent = substr(tmp.agent, -4) and up.customer_code = tmp.code
);

Update from two tables oracle [duplicate]

This question already has answers here:
Update statement with inner join on Oracle
(15 answers)
Closed 4 years ago.
I have two tables.
J_YAD_PICT (table name) , GALLERY_DISP_FLG (column)
J_YAD_CGR_PICT (table name) , Y_CGR_FLG (column)
when Y_CGR_FLG not null in J_YAD_CGR_PICT, then GALLERY_DISP_FLG needed to set as 1.
I have executed this
Update A
SET A.GALLERY_DISP_FLG =
(CASE WHEN b.Y_CGR_FLG IS NOT NULL) THEN '1'
ELSE A.GALLERY_DISP_FLG
END
FROM J_YAD_PICT A inner join J_YAD_CGR_PICT B
on A.YP_ID = B.YP_ID;
But given this error :
SQL Error: ORA-00905: missing keyword
Could anyone help me ?
which table you use alias A?
i suggest try like this
Update J_YAD_PICT A SET
A.GALLERY_DISP_FLG = (CASE WHEN b.Y_CGR_FLG IS NOT NULL) THEN '1'
ELSE A.GALLERY_DISP_FLG
END
FROM J_YAD_PICT A inner join J_YAD_CGR_PICT B on A.YP_ID = B.YP_ID;
Something like this?
update j_yad_pict p set
p.gallery_disp_flg = (select case when c.y_cgr_flg is not null then '1'
else p.gallery_disp_flg
end
from j_yad_cgr_pict c
where c.yp_id = p.yp_id
)
where exists (select null from j_yad_cgr_pict c1
where c1.yp_id = p.yp_id
);
EXISTS part of the query is here so that you wouldn't update rows (to NULL) that don't have a match in J_YAD_CGR_PICT table.
When update table J_YAD_PICT, must be this table connect from table in inner select
UPDATE J_YAD_PICT A
SET A.GALLERY_DISP_FLG = (
SELECT CASE WHEN b.Y_CGR_FLG IS NOT NULL THEN '1' ELSE A.GALLERY_DISP_FLG END
FROM J_YAD_PICT A2
INNER JOIN J_YAD_CGR_PICT B ON A.YP_ID = B.YP_ID
WHERE A.ID = A2.ID);

i have sql script which uses two query to get the result that i expect , how can i achieve this with the single query ,example below

query1 where condition = "condition1" ; queryresult1 = number1
query2 where condition = "condition2" ; queryresult2 = number2
I want number1-number2 , how can i make this possible with just a single query
Assuming i understand your question correctly, easiest way is joining two table and perform your whatever calculation.
select valueone, valuetwo, valueone - valuetwo as finalresult
from (select 18 as valueone from dual where 1 = 1) -- query one)
inner join (select 6 as valuetwo from dual where 1 = 1) -- query two)
on 1 = 1 -- join condition
where 1 = 1; -- some condition

Query to find Index bloat

I need a query to find whether index bloat on a table. I saw some queries where they are comparing table size with index size. If there is any other approach, please share the query.
I am using Greenplum 4.3 (which is based Postgres 8.2)
Bloat Score Query
The following SQL query will examine each table in the XML schema and identify dead rows (tuples) that are wasting disk space.
SELECT schemaname || '.' || relname as tblnam,
n_dead_tup,
(n_dead_tup::float / n_live_tup::float) * 100 as pfrag
FROM pg_stat_user_tables
WHERE schemaname = 'xml' and n_dead_tup > 0 and n_live_tup > 0 order by pfrag desc;
If this query returns a high percentage ( pfrag ) of dead tuples, the VACUUM command may be used to reclaim space.
7 Considered to be high
From wiki.postgres.org
SELECT
current_database(), schemaname, tablename, /*reltuples::bigint, relpages::bigint, otta,*/
ROUND((CASE WHEN otta=0 THEN 0.0 ELSE sml.relpages::float/otta END)::numeric,1) AS tbloat,
CASE WHEN relpages < otta THEN 0 ELSE bs*(sml.relpages-otta)::BIGINT END AS wastedbytes,
iname, /*ituples::bigint, ipages::bigint, iotta,*/
ROUND((CASE WHEN iotta=0 OR ipages=0 THEN 0.0 ELSE ipages::float/iotta END)::numeric,1) AS ibloat,
CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta) END AS wastedibytes
FROM (
SELECT
schemaname, tablename, cc.reltuples, cc.relpages, bs,
CEIL((cc.reltuples*((datahdr+ma-
(CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)) AS otta,
COALESCE(c2.relname,'?') AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages,
COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta -- very rough approximation, assumes all cols
FROM (
SELECT
ma,bs,schemaname,tablename,
(datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr,
(maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2
FROM (
SELECT
schemaname, tablename, hdr, ma, bs,
SUM((1-null_frac)*avg_width) AS datawidth,
MAX(null_frac) AS maxfracsum,
hdr+(
SELECT 1+count(*)/8
FROM pg_stats s2
WHERE null_frac<>0 AND s2.schemaname = s.schemaname AND s2.tablename = s.tablename
) AS nullhdr
FROM pg_stats s, (
SELECT
(SELECT current_setting('block_size')::numeric) AS bs,
CASE WHEN substring(v,12,3) IN ('8.0','8.1','8.2') THEN 27 ELSE 23 END AS hdr,
CASE WHEN v ~ 'mingw32' THEN 8 ELSE 4 END AS ma
FROM (SELECT version() AS v) AS foo
) AS constants
GROUP BY 1,2,3,4,5
) AS foo
) AS rs
JOIN pg_class cc ON cc.relname = rs.tablename
JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname = rs.schemaname AND nn.nspname <> 'information_schema'
LEFT JOIN pg_index i ON indrelid = cc.oid
LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid
) AS sml
ORDER BY wastedbytes DESC

Resources