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
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
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 ;
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.
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?
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.