Drop table if exists in PostgreSQL database - postgresql

I am trying to drop table if it is exists in the present working database of PostgreSQL. For which I am trying the following query.
Example:
var1 := 'IF EXISTS (select * from INFORMATION_SCHEMA.TABLES WHERE name = ''Table_'|| Suffix ||''') then
DROP TABLE Table_'||Suffix||'';
execute var1;
But getting error near IF.

execute executes SQL statements, not PL/pgSQL commands. The IF statement is a PL/pgSQL construct.
In any case you can use
DROP TABLE IF EXISTS ...
(see the manual page for DROP).

Related

How to use a subquery as a database name in a DDL command?

I am wondering if it's possible to use the result of a subquery as database name in a PostgreSQL (9.5.1) DDL statement.
For example, I wanted to alter the current database with something like:
ALTER DATABASE (SELECT current_database()) SET a_var TO 'a_value';
If I run this, an error occurs:
ERROR: syntax error at or near "("
LINE 1: ALTER DATABASE (SELECT current_database()) SET ...
What's the correct way to use the sub-query (if possible)?
You need dynamic SQL for that:
DO
$do$
BEGIN
EXECUTE format($f$ALTER DATABASE %I SET x.a_var TO 'a_value'$f$, current_database());
END
$do$;
Using format() to escape the db name safely while being at it.
BTW, to unset:
ALTER DATABASE your_db RESET x.a_var;
To see the current setting:
SELECT current_setting('x.a_var');
(The DB default is not active before you start a new session.)
Related:
Table name as a PostgreSQL function parameter
Error when setting n_distinct using a plpgsql variable

Executing dynamic SQL in Postgres 8.2

I am trying to create a table inside a function using dynamic SQL and immediately copy it into another table.
execute 'create table week_temp as
select w.*, ww.*
from employer_weekly w
left join employer_weekly_' || $1 || '_2 ww
on w.w_employer::int = ww.emp_' || $1 || '::int';
drop table if exists employer_weekly;
create table employer_weekly as select * from week_temp;
I am receiving the following error:
Error : ERROR: relation with OID 9288742 does not exist
CONTEXT: SQL statement "create table employer_weekly as select * from
week_temp"
Checking manually, I can see week_temp and can access it correctly.
Would appreciate any clues!
What #a_horse_with_no_name said.
But - the problem you are seeing is that the non-dynamic statements in your function are being compiled. This means the "FROM week_temp" is looking at an older version of week_temp that no longer exists. Make that statement dynamic SQL too and it should work.

Error while using Trigger in Greenplum

If any of you created/tried Triggers on Greenplum, Please help me to resolve this
I have a table where a "id" column has some value, and i want to put a trigger
Before insert any data in this table, it should call a function/trigger to check
a) if the data is available for "id" in Parent table or not
b) there is already a row available for given "id"
--Table DDL
create table test_trigger(id integer, details text);
--Trigger Function
create or replace function insert_row_trigger() returns trigger as $$
begin
if exists (SELECT 1 FROM test_trigger WHERE id = NEW.id)
Then
Return NULL;
else
Return NEW;
End If;
End;
$$ language plpgsql;
--Trigger Creation
create trigger my_trigger before insert on test_trigger for each row execute procedure insert_row_trigger();
--Drop Trigger
drop trigger my_trigger on test_trigger
ERROR
ERROR: function cannot execute on segment because it accesses
relation "jiodba.test_trigger" (functions.c:151) (seg1
SRDCB0002GPM02:40001 pid=11366) (cdbdisp.c:1477) DETAIL: SQL
statement "SELECT exists (SELECT 1 FROM test_trigger WHERE id = $1 )"
PL/pgSQL function "insert_row_trigger" line 2 at if
********** Error **********
ERROR: function cannot execute on segment because it accesses relation
"jiodba.test_trigger" (functions.c:151) (seg1 SRDCB0002GPM02:40001
pid=11366) (cdbdisp.c:1477) SQL state: XX000 Detail: SQL statement
"SELECT exists (SELECT 1 FROM test_trigger WHERE id = $1 )" PL/pgSQL
function "insert_row_trigger" line 2 at if
Please help me on this.
~I also read somewhere that triggers are not supported in GP
Trigger is a function executed on the segment level for each of the input data rows. The issue is that in Greenplum you cannot execute any query from the segment level as it would require each segment to reconnect to the master to execute it separately, which will cause a connection bloat for a big systems.
The way to overcome this is for instance this way:
Have an unique index on the Parent table
In a single transaction, execute two statements: first, insert into parent select all the rows that does not exist in parent table. Second, insert into target table all the input rows with the keys just inserted to the parent table.
In general, you will have the same logic, but without trigger
Create a RULE statement is a alternative to triggers in GP.
Try this:
https://gpdb.docs.pivotal.io/5280/ref_guide/sql_commands/CREATE_RULE.html#:~:text=The%20Greenplum%20Database%20rule%20system,used%20on%20views%20as%20well.

SELECT .. INTO to create a table in PL/pgSQL

I want to use SELECT INTO to make a temporary table in one of my functions. SELECT INTO works in SQL but not PL/pgSQL.
This statement creates a table called mytable (If orig_table exists as a relation):
SELECT *
INTO TEMP TABLE mytable
FROM orig_table;
But put this function into PostgreSQL, and you get the error: ERROR: "temp" is not a known variable
CREATE OR REPLACE FUNCTION whatever()
RETURNS void AS $$
BEGIN
SELECT *
INTO TEMP TABLE mytable
FROM orig_table;
END; $$ LANGUAGE plpgsql;
I can SELECT INTO a variable of type record within PL/pgSQL, but then I have to define the structure when getting data out of that record. SELECT INTO is really simple - automatically creating a table of the same structure of the SELECT query. Does anyone have any explanation for why this doesn't work inside a function?
It seems like SELECT INTO works differently in PL/pgSQL, because you can select into the variables you've declared. I don't want to declare my temporary table structure, though. I wish it would just create the structure automatically like it does in SQL.
Try
CREATE TEMP TABLE mytable AS
SELECT *
FROM orig_table;
Per http://www.postgresql.org/docs/current/static/sql-selectinto.html
CREATE TABLE AS is functionally similar to SELECT INTO. CREATE TABLE AS is the recommended syntax, since this form of SELECT INTO is not available in ECPG or PL/pgSQL, because they interpret the INTO clause differently. Furthermore, CREATE TABLE AS offers a superset of the functionality provided by SELECT INTO.

mysqli cannot call stored procedure

Procedure
delimiter $$
drop procedure if exists db1.test;
create procedure db1.test()
deterministic
begin
select * from table1;
end$$
delimiter ;
php code:
$conn = new mysqli('localhost','username','passwd','db1');
$query1 = 'select * from table1';
$query2 = 'call test()';
Then $conn->query($query1) works while $conn->query($query2) returns bool(false).
But in mysql, both query1 and query2 work.
What did I miss here? Thanks!
Okay, if it's not the syntax, it could be permissions. Did you grant execute privileges to the user for this database?
Edit:
Here's the SQL to do this:
GRANT EXECUTE ON `db1` . * TO 'user'#'localhost';
(Even if a user has all the permissions required to do the SQL inside the stored procedure as individual queries, you'd still need the EXECUTE privilege to actually call the procedure.)
Are you sure the procedure is being created? Both MySQL Workbench and phpMyAdmin are telling me there's a syntax error in select * from table; --- probably because table is a reserved word? This worked in MySQL Workbench:
USE `db1`;
DROP procedure IF EXISTS `test`;
DELIMITER $$
USE `db1`$$
CREATE PROCEDURE `db1`.`test` ()
BEGIN
select * from `table`;
END
$$
DELIMITER ;
Note the addition of backticks to table. With that change on my system, $query2 succeeds but $query1 fails (with or without the change to the procedure of course)