I'm new to postgres, for a scenario i stored SQL statements inside a table with respective to table name. in the function i'm trying to filter the table name by passing them as a parameter to get the query from the table. But when i execute the query from the variable it gives out error
"SQL Error [42P01]: ERROR: relation "public.table_name" does not exist
Where: PL/pgSQL function ops_data_refresh(text) line 45 at EXECUTE"
execute format('select query from public.ops_dw_table_load where target_table=''%s'' and is_active =true',main_table)
into qry1;
if qry1 is not null then
raise notice '%',qry1;
execute qry1;
raise notice output insert into public.table_name select * from stage.table_name;
with raise notice im able to see the query which is in the table, if I run it manually things are working fine. but when running from function it throws the above error.
There is an SQL injection bug in your code. It should be:
EXECUTE format('SELECT ... target_table = %L ...', main_table);
But the problem is in the second EXECUTE: the query references a table that does not exist. Either change the query or create the table.
Related
I'm trying to build a trigger on a table, depending on other tables. So after search I have something like this
in the trigger :
begin
table_name=select (...) from information schema ;
execute format('some stuff
for i in select ... loop
insert into table (...) select (...) from %I
end loop',table)
But when firing the trigger I get this error:
SQL Error [42601]: ERROR: syntax error on or near « FOR »
I can't understand why-any ideas ?
With EXECUTE (dynamic SQL) you can only execute SQL statements. You are trying to execute a PL/pgSQL block.
You have three options:
The query string only contains the INSERT statement, and the loop is regular SQL.
The query string is a DO SQL statement that contains the whole block.
Rather than writing a FOR loop, write a dynamic statement like
INSERT INTO ...
SELECT ... FROM %I
I have a stored procedure that performs inserts and updates in the tables. The need to create it was to try to centralize all the scan functions before inserting or updating records. Today the need arose to return the value of the field ID of the table so that my application can locate the registry and perform other stored procedures.
Stored procedure
SET TERM ^ ;
CREATE OR ALTER procedure sp_insupd (
iaction varchar(3),
iusuario varchar(20),
iip varchar(15),
imodulo varchar(30),
ifieldsvalues varchar(2000),
iwhere varchar(1000),
idesclogs varchar(200))
returns (
oid integer)
as
declare variable vdesc varchar(10000);
begin
if (iaction = 'ins') then
begin
vdesc = idesclogs;
/*** the error is on the line below ***/
execute statement 'insert into '||:imodulo||' '||:ifieldsvalues||' returning ID into '||:oid||';';
end else
if (iaction = 'upd') then
begin
execute statement 'select '||:idesclogs||' from '||:imodulo||' where '||:iwhere into :vdesc;
execute statement 'execute procedure SP_CREATE_AUDIT('''||:imodulo||''');';
execute statement 'update '||:imodulo||' set '||:ifieldsvalues||' where '||:iwhere||';';
end
insert into LOGS(USUARIO, IP, MODULO, TIPO, DESCRICAO) values (
:iusuario, :iip, :imodulo, (case :iaction when 'ins' then 1 when 'upd' then 2 end), :vdesc);
end^
SET TERM ; ^
The error in the above line is occurring due to syntax error. The procedure is compiled normally, that is, the error does not happen in the compilation, since the line in question is executed through the "execute statement". When there was no need to return the value of the ID field, the procedure worked normally with the line like this:
...
execute statement 'insert into '||:imodulo||' '||:ifieldsvalues||';';
...
What would be the correct way for the value of the ID field to be stored in the OID variable?
What is REAL VALUE in ifieldsvalues ?
you can not have BOTH
'insert into '||:imodulo||' '||:ifieldsvalues
'update '||:imodulo||' set '||:ifieldsvalues
because methods to specify column names and column values in INSERT and UPDATE statements is fundamentally different!!! You either would have broken update-stmt or broken insert-stmt!
The error in the above line is occurring due to syntax error
This is not enough. Show the real error text, all of it.
It includes the actual command you generate and it seems you had generated it really wrong way.
all the scan functions before inserting or updating records
Move those functions out of the SQL server and into your application server.
Then you would not have to make insert/update in that "strings splicing" way, which is VERY fragile and "SQL injection" friendly. You stepped into the road to hell here.
the error does not happen in the compilation
Exactly. And that is only for starters. You are removing all the safety checks that should had helped you in applications development.
http://searchsoftwarequality.techtarget.com/definition/3-tier-application
https://en.wikipedia.org/wiki/Multitier_architecture#Three-tier_architecture
http://bobby-tables.com
On modern Firebird versions EXECUTE STATEMENT command can have the same INTO clause as PSQL SELECT command.
https://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-psql-coding.html#fblangref25-psql-execstmt
Use http://translate.ru to read http://www.firebirdsql.su/doku.php?id=execute_statement
Or just see SQL examples there. Notice, however, those examples all use SELECT dynamic command, not INSERT. So I am not sure it would work that way.
This works in Firebird 2.5 (but not in Firebird 2.1) PSQL blocks.
execute statement 'insert into Z(payload) values(2) returning id' into :i;
To run it from IBExpert/FlameRobin/iSQL interactive shell add that obvious boilerplate:
execute block returns (i integer) as
begin
execute statement 'insert into Z(payload) values(2) returning id' into :i;
suspend;
end
I am new to postgres and running following dynamic query
EXECUTE 'Select * from products';
I get following response.
ERROR: syntax error at or near "'Select * from products'"
LINE 1: EXECUTE 'Select * from products';
I Know this would be something basic I m missing
There is the EXECUTE statement of plpgsql, which would do what you are trying to do - execute an SQL query string. You tagged dynamic, so this may be what you are looking for.
Only works inside plpgsql functions or DO statements (anonymous code blocks). The distinction between EXECUTE and SQL-EXECUTE made clear in the fine manual:
Note: The PL/pgSQL EXECUTE statement is not related to the EXECUTE SQL
statement supported by the PostgreSQL server. The server's EXECUTE
statement cannot be used directly within PL/pgSQL functions (and is
not needed).
If you want to return values from a dynamic SELECT query as your example indicates, you need to create a function. DO statements always return void. More about returning values from a function in the very fine manual.
From the fine manual:
Synopsis
EXECUTE name [ ( parameter [, ...] ) ]
Description
EXECUTE is used to execute a previously prepared statement.
So EXECUTE doesn't execute a string of SQL, it execute a prepared statement that is identified by a name and you need to prepare the statement separately using PREPARE:
=> prepare stmt as select * from products;
=> execute stmt;
-- "select * from products" output goes here...
The MySQL Stored Procedure was:
BEGIN
set #sql=_sql;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
set _ires=LAST_INSERT_ID();
END$$
I tried to convert it to:
BEGIN
EXECUTE _sql;
SELECT INTO _ires CURRVAL('table_seq');
RETURN;
END;
I get the error:
SQL error:
ERROR: relation "table_seq" does not exist
LINE 1: SELECT CURRVAL('table_seq')
^
QUERY: SELECT CURRVAL('table_seq')
CONTEXT: PL/pgSQL function "myexecins" line 4 at SQL statement
In statement:
SELECT myexecins('SELECT * FROM tblbilldate WHERE billid = 2')
The query used is for testing purposes only. I believe this function is used to get the row id of the inserted or created row from the query. Any Suggestions?
When you create tables with serial columns, sequences are, by default, named as tablename_columnname_seq, but it seems that you're trying to access tablename_seq. So with a table called foobar and primary key column foobar_id it ends up being foobar_foobar_id_seq.
By the way, a cleaner way to get the primary key after an insert is using the RETURNING clause in INSERT. E.g.:
_sql = 'INSERT INTO sometable (foobar) VALUES (123) RETURNING sometable_id';
EXECUTE _sql INTO _ires;
PostgreSQL is saying that there is no sequence called "table_seq". Are you sure that that is the right name? The name you would use would depend on what is in _sql as each SERIAL or BIGSERIAL gets its own sequence, you can also define sequences and wire them up by hand.
In any case, lastval() is a closer match to MySQL's LAST_INSERT_ID(), lastval() returns the most recently returned value from any sequence in the current session:
lastval
Return the value most recently returned by nextval in the current session. This
function is identical to currval, except that instead of taking the sequence name
as an argument it fetches the value of the last sequence used by nextval in the
current session. It is an error to call lastval if nextval has not yet been called
in the current session.
Using lastval() also means that you don't have to worry about what's in _sql, unless of course it doesn't use a sequence at all.
is it possible to execute a storep procedure inside select query ?
select e.Name, dbo.get_sth e.Id
from emp e
I get the error
Incorrect syntax near 'e.Id'
No. But you can execute a function inside a select statement. So recreate your Stored Procedure as a function and this should work.
It will be called for every row so be careful of performance if returning many rows.