Wrong symbol inside replace function (PL/SQL, ORACLE) - sql

I have below procedure inside package:
PROCEDURE test1
IS
InsertST varchar2(32000) : = 'INSERT INTO tableA (col1, col2)
(select cola,
INITCAP(REPLACE(colX, '_', ''))
from tableB))';
Begin
execute immediate InsertST;
END
during compilation I got error:
Error(1177,45): PLS-00103: Encountered the symbol "_" when expecting one of the following: * & = - + ; < / > at in is mod remainder not rem <> or != or ~= >= <= <> and or like like2 like4 likec between || member submultiset
Something is wrong with "_" inside function: INITCAP(REPLACE(colX, '_', ''))
How to fix it? Maybe is other way?

The quoted string starting 'INSERT ends at colX, '. To quote a quote you need to either double up the quotes:
'INSERT INTO tableA (col1, col2)
(select cola,
INITCAP(REPLACE(colX, ''_'', ''''))
from tableB))'
or else use q-quoting syntax:
q'[INSERT INTO tableA (col1, col2)
(select cola,
INITCAP(REPLACE(colX, '_', ''))
from tableB))]';
Also, the assignment operator is := not : =.
It looks like you want to generate a statement like this:
insert into tablea ( col1, col2 )
select cola, initcap(replace(colx, '_', ''))
from tableb
which has a couple less brackets.
It doesn't look like it needs to be dynamic at all, but I'm assuming this is a simplified version of something that does.

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

SQL: Problems translating recursive connect by Statement for Postgres

I try to translate the following oracle sql, which inserts 1000 rows with incremental values into a table:
insert into tableName (col1, col2, col3)
select 'AN' || (1000000 + ROWNUM), 'EXT' || (9000000 + ROWNUM), ROWNUM
from dual
Connect By ROWNUM <= 1000 ;
For Postgres support, i know i can substitute ROWNUM with ROW_NUMBER() OVER (), but i'm really getting a headache about translating the connect by statement. I have read about CTEs but i don't get how i can use this with an insert statement.
Does anyone know how to write this statement for postgresql? Thanks.
You can generate a series and just use that:
insert into tableName (col1, col2, col3)
select 'AN' || (1000000 + g.n), 'EXT' || (9000000 + g.n), g.n
from generate_series(1, 1000) g(n);
Try generate_series.
select 'AN' || (1000000 + ROWNUM), 'EXT' || (9000000 + ROWNUM),
ROWNUM from generate_series(1,10000) as rownum ;

Query which inserts then Updates 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.

Query who generates insert statements : invalid number

I'm trying to execute a query who generates inserts statements, like that :
select
'insert into MYTABLE (
ID,
COLUMN_A,
COLUMN_B)
values (' +
ID + ',' +
COLUMN_A + ',' +
COLUMN_B
as INSERTGENERATOR from MYTABLE;
But I have this error :
ORA-01722: invalid number
01722. 00000 - "invalid number"
*Cause:
*Action:
Why ?
I tried with || instead of +, and with to_char, but it but it does not change.
Don't put end of lines within quotes. And || is used to concatenate.
select
'insert into MYTABLE (ID, COLUMN_A, COLUMN_B) values (' ||
ID || ',' ||
COLUMN_A || ',' ||
COLUMN_B || ');'
as INSERTGENERATOR from MYTABLE;
This works:
SELECT
'INSERT INTO MYTABLE
(ID, COLUMN_A, COLUMN_B)
VALUES (' ||
ID || ',' ||
COLUMN_A || ','||
COLUMN_B || ');'
AS INSERTGENERATOR
FROM MYTABLE;
Sample SQL Fiddle
Get rid of all the pain while concatenating string literals using pipes "||" etc. Just use the latest string literal feature q'[]'.
SQL> SELECT q'[insert into MYTABLE (
2 ID,
3 COLUMN_A,
4 COLUMN_B)
5 values ('ID', 'COLUMN_A','COLUMN_B')]'
6 AS INSERTGENERATOR
7 FROM DUAL
8 /
INSERTGENERATOR
-------------------------------------------
insert into MYTABLE (
ID,
COLUMN_A,
COLUMN_B)
values ('ID', 'COLUMN_A','COLUMN_B')
SQL>
Neat, isn't it?

Dynamically look up column names for a table while in an sql query

I'm writing SQL (for Oracle) like:
INSERT INTO Schema1.tableA SELECT * FROM Schema2.tableA;
where Schema1.tableA and Schema2.tableA have the same columns. However, it seems like this is unsafe, since the order of the columns coming back in the SELECT is undefined. What I should be doing is:
INSERT INTO Schema1.tableA (col1, col2, ... colN)
SELECT (col1, col2, ... colN) FROM Schema2.tableA;
I'm doing this for lots of tables using some scripts, so what I'd like to do is write something like:
INSERT INTO Schema1.tableA (foo(Schema1.tableA))
SELECT (foo(Schema1.tableA)) FROM Schema2.tableA;
Where foo is some nifty magic that extracts the column names from table one and packages them in the appropriate syntax. Thoughts?
This PL/SQL should do it:
declare
l_cols long;
l_sql long;
begin
for r in (select column_name from all_tab_columns
where table_name = 'TABLEA'
and owner = 'SCHEMA1'
)
loop
l_cols := l_cols || ',' || r.column_name;
end loop;
-- Remove leading comma
l_cols := substr(l_cols, 2);
l_sql := 'insert into schema1.tableA (' || l_cols || ') select '
|| l_cols || ' from schema2.tableA';
execute immediate l_sql;
end;
/
You may need to construct the insert statements dynamically using USER_TAB_COLUMNS and execute them using EXECUTE IMMEDIATE.