Query which inserts then Updates SQL - sql

Is it possible to have an insert statement and once that is complete straight away run an update statement?
So Here are my statements:
Insert
truncate table table1;
INSERT INTO table2 (name,value, ATY)
SELECT table1.name,table1.Value,table1.ATY
FROM table1;
As soon as that is complete, I need the following update to run:
Update
update table2
SET value=TRIM( BOTH '+' FROM REPLACE( '+' || value || '+', '++', '+000+' ) )
Is this possible?

Why not do both in one statement?
truncate table table2;
INSERT INTO table2 (name, value, ATY)
SELECT t1.name,
TRIM( BOTH '+' FROM REPLACE( '+' || t1.value || '+', '++', '+000+' ) ),
t1.ATY
FROM table1 t1;
Note: I assume that you intend to truncate table2, not table1. If you truncate table1, then the insert will not do anything because the table will be empty.

Related

How to dynamically pass column names to a query?

Below is my problem and desired solution.
Query1:
Select colnames from table1;
Query1 Result:
col1
col2
col3
col4
Query2:
Select a1.*
from table2 a1;
-- should translate to
select a1.col1, a1.col2, a1.col3, a1.col4 from table2 a1;
My first query will give the list of column names, I need to replace the .* with those column names in my second query. How can I achieve this?
You are looking for dynamic SQL. The idea is to generate the query string from the results of a SQL query. You can then run it with execute immediate.
In your use case, that would look like:
declare
p_sql varchar2(100);
begin
select
'select '
|| listagg('a1.' || colnames, ', ') within group(order by colnames)
|| ' from table2 a1'
into p_sql
from table1;
dbms_output.put_line('sql: ' || p_sql); -- debug
execute immediate p_sql; -- execute
end;
/
For your sample data, this generates:
dbms_output:
sql: select a1.col1, a1.col2, a1.col3, a1.col4 from table2 a1

Oracle SQL procedure with table name as input using dynamic SQL

I see a lot of similar questions already answered including here, here and here. The list goes on.
What makes mine different? These other questions seem to be very simple, one line sql statements. I have a more complex merge statement that spans multiple lines and no matter how I have tried to put the statement together it gives me a compilation error. Below is one such attempt.
It is a long statement, the only dynamic parts are 2 nonconsecutive lines at the very beginning as shown below. I have tried to make the whole statement a string and execute it, but I get an error that the string is too long, plus this makes it very hard to read so it is undesirable. I have also tried breaking up the 2 parts that require dynamic sql into 2 execute immediate blocks, but that throws a compilation error as well.
My code
create or replace procedure table_sync(
table_name in varchar2,
source_node in varchar2
)
is
begin
execute immediate
'merge into ' || table_name || ' dest' /* ---- first line ---- */
using (select date_time, version_date, data_entry_date, value
'from username.' || table_name || '#' || source_node /* ---- second line ---- */
where data_entry_date < (sysdate - 10)) src
on ( dest.date_time = src.date_time and
dest.version_date = src.version_date
)
when matched then
update
set
dest.data_entry_date = src.data_entry_date,
dest.value = src.value
where
(case
.
.
.
Is there a way to put combine this dynamic statement?
Thank you
Using merge to achieve this is a good approach, but your statement is missing some quotes. Here is a fiddle with an example, similar to what you are trying to do.
From that fiddle, create test data:
create table table1(id varchar2(30), username varchar2(30), fullname varchar2(30));
create table table2(id varchar2(30), username varchar2(30), fullname varchar2(30));
insert into table1 values('a1', 'b1', 'c1');
insert into table1 values('a2', 'b2', 'c2');
insert into table1 values('a3', 'b3', 'c3');
insert into table1 values('a4', 'b4', 'c4');
insert into table2 values('a1', 'b1', 'c1');
insert into table2 values('a2', 'b2', 'c2');
insert into table2 values('a3', 'b3', 'c3');
Your function:
CREATE OR replace PROCEDURE Table_sync(table_name IN VARCHAR2)
IS
stmnt CLOB;
BEGIN
stmnt := 'merge into ' || table_name || ' dest '
|| 'using (select id, username from table1) src '
|| 'on (dest.id = src.id) '
||
' when matched then update set dest.fullname = src.username || src.id '
|| ' where dest.username like ''%2'' '
|| ' when not matched then insert (id, username, fullname) values(src.id, src.id||src.username, src.username||src.username) '
;
EXECUTE IMMEDIATE stmnt;
END table_sync;
If the record in table1 exists with the same value in col1 as the column in table2, then it will update it based on a condition, if the record does not exist, it will insert it.
You can write all your conditions inside that where statement and pay attention to the 2xsingle quotes used for quoting values in the dynamic query.

Trigger code not working in oracle to avoid duplicate data

Below trigger code(converted from MSSQL) in oracle is not working.
The two columns should not have duplicate row in the table. I'm creating a trigger for accomplishing this.
Can anyone help in updating/correcting the above code to be used in my trigger?
/*
**Unique Constraint for TestOracle - TestTinyInt.
*/
if (Update(UpdOperation) or Update(TestTinyInt)) THEN
IF Exists(
SELECT * FROM inserted i INNER LOOP JOIN TestOracle x ON
(i.TestTinyInt=x.TestTinyInt)
WHERE i.updoperation IN (0, 1) AND x.updoperation IN (0, 1) GROUP BY x.TestTinyInt
HAVING COUNT(*) > 1)
BEGIN
RAISERROR( 'Invalid attempt to enter duplicate TestTinyInt in TestOracle', 16, -1 )
ROLLBACK TRAN
RETURN
END
END
The best way is to create 2 unique index on each of columns. By doing this you are eliminating duplication in particual column(like #a_horse_with_no_name mentioned).
For other case you don't need to use triger, you need only simple where condition
where Column_A not in (select Column_B from table) and Column_B not in (Select Column_A in table).
EDIT:
It if have to be done in trigger THEN :
create or replace trigger ... instead of insert or update on ...
Declare
dummy number;
Begin
select 1 into dummy from dual where :new.Column_A in (select Column_B from table) or new:.Column_B in (Select Column_A in table);
if dummy <> 1 THEN
INSERT
END IF;
END;
EDIT2: IF you don't want unique index and tirgger here is solution :
create or replace trigger ... instead of insert or update on ...
Declare
dummy number;
Begin
select count(*) into dummy from(
SELECT COL1 FROM (
(select :new.Column_A col1 from dual
UNION
select :new.Column_B from dual))
INTERSECT
SELECT COL2 FROM (
( SELECT COLUMN_A COL2 from table
UNION
SELECT COLUMN_B from table));
if dummy = 0 THEN
INSERT
END IF;
END;

Postgres array value must starts

I want to make an array and put into it two id's, but I got a mistake:
array value must start with “{” or dimension information
ids_list character varying[] := ' || (SELECT COALESCE(quote_literal((array_agg(DISTINCT house_guid)) || ''',''' || quote_literal(array_agg(DISTINCT guid))), 'NULL') FROM tb) || ';
use array_agg function
with t1 as
(
select * from
(
select 'test_SQL_01' as ID
union
select 'test_SQL_02_PQR_01'
union
select 'test_SQL_03_055'
union
select 'test_SQL_04_ABC_99'
) as t
) select array_agg(ID) from t1
You seem to be using this inside a PL/pgSQL function. You should be using SELECT ... INTO variable FROM... instead:
declare
ids_list character varying[];
begin
.....
select array_agg(id)
into ids_list
from (
select house_guid
from tab
union
select guid
from tab
) t;
.... work with the ids_list variable
end;
The UNION will automatically remove all duplicates (as you tried to do with DISTINCT.

Oracle Select which produce Insert into

I have query like
SELECT 'Insert INTO FOO(ID,NAME) values ('||id|| ',' ||NAME||');' as query
FROM FOO
This is just an example as I can't provide real query example. So, DON'T pay attention how it works just believe that it works as it should.
Question:
If NULL values exists in selected rows it just produces '' in INSERT INTO query. So I am getting an error while trying to execute insert query. How can I force SELECT query to return NULL instead of ''?
Example:
I have
Insert INTO FOO(ID,NAME) values (12,);
I want to have
Insert INTO FOO(ID,NAME) values (12,NULL);
Try using CASE EXPRESSION :
SELECT 'Insert INTO FOO(ID,NAME)
values ('||CASE WHEN id = '''' then 'NULL' else id end||','|| CASE WHEN NAME = '''' THEN null else NAME end || ');' as query
FROM FOO
I am guessing that NAME is a string, so it should be surrounded by single quotes. So, this might be the query you want:
SELECT 'Insert INTO FOO(ID,NAME) values (' || id || ', ''' || NAME ||''');' as query
FROM FOO;
If the issue is id, then you can do:
SELECT 'Insert INTO FOO(ID,NAME) values (' || (CASE WHEN id IS NULL THEN 'NULL' ELSE CAST(id AS VARCHAR2(255)) END) ||
', ''' || NAME ||''');' as query
FROM FOO;