I'm very familiar with MSSQL but I need to work with some postgres stuff today. The end goal is to return the new id of a table for use elsewhere but since I'm unfamiliar with the syntax of postgress, I seem to be having some trouble.
Problem 1:
in MSSQL I would:
delcare #test_number int
select #test_number = 42
print #test_number
in Postgres I'm trying:
test_number integer;
test_number := 42
print test_number
but it doesnt like the first line:
ERROR: syntax error at or near "test_number"
LINE 1: test_number integer;
If I can figure this out, I think I've got my real problem solved which would be to do something like:
Problem 2:
in MSSQL I would:
declare #new_id int
insert into some_table (data1. data2)
select #new_id = ##identity
-- now use #new_id for w/e you want
in Postgres I'm trying:
new__id integer;
new_id := insert into some_table (data1, data2) returning id;
-- now use new_id for w/e you want
A quick search on Google gives the following answer.
How do you use variables in a simple PostgreSQL script?
It looks like you basically declare an anonymous inline pgsql function in your query. Also looks like it's new to Postgres 9.
Related
This covers most use cases How do you use variables in a simple PostgreSQL script? but not the select clause.
This code produces an error column "ct" does not exist"
DO
$$
declare CT timestamp := '2020-09-04 23:59:59';
select CT,5 from job;
$$;
I can see why it would interpret CT as a column name. What's the Postgres syntax required to refer to a variable in the context of the select clause?
I would expect that query to return
'2020-09-04 23:59:59',5
for each row in the job table.
Addendum to the accepted answer
My use case doesn't return rows. Instead, the result of the select is consumed by an insert statement. I'm transforming rows from staging tables into other tables and adding value like the import date and the identity owning the inserts. It's these values that are provided by the variables - they are used in several such transforms and the point of the variable is to let me set each value once up the top of the script.
Because the rows are consumed like this, it turns out that I don't need a function wrapping this code. It's a bit inconvenient to test since I can't run the select and look at the outcome without copying it and pasting in literals, but at least it's possible to use variables. My working script looks like this:
do
$$
declare ct timestamp := '2020-09-04 23:59:59';
declare cb int := 2;
declare iso8601 varchar(50) := 'YYYY-MM-DD HH24:MI:SS';
declare USAdate varchar(50) := 'MM-DD-YYYY HH24:MI:SS';
begin
delete from dozer_wheel_loader_equipment_movement where created = ct;
INSERT INTO dozer_wheel_loader_equipment_movement
(site, primary_category_id, machine, machine_class, x, y, z, timestamp_local, created, created_by)
select site ,mc.id ,machine , machineclass ,x,y,z,to_timestamp(timestamplocal, iso8601), ct, cb
from stage_dozer_csv d join machine_category mc on d.primarycategory = mc.short_code;
...
end
$$
There is a lot of worthwhile related reading at How to declare a variable in a PostgreSQL query
There are few things about variables in PostgreSQL.
Variable can not be used in Plain SQL in Postgres. So you have to use any pl language i.e. plpgsql to use this. You have tried the same in your example.
In your DO block you have missed the Begin and End, So you have to write it like below
DO
$$
begin
declare CT timestamp := '2020-09-04 23:59:59';
select CT,5 from job;
end
$$;
But when you read the official documentation of DO Statement, it says DO will allow to run the anonymous code but it returns void, that's why above code will throw following error:
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function inline_code_block line 4 at SQL statement
So there is only one way - wrap this code block in a Function like below:
create or replace function func() returns table(col1 timestamp, col2 int )
AS
$$
declare ct timestamp := '2020-09-04 23:59:59';
begin
return query
select CT,5 from job;
end;
$$
language plpgsql
and you can call it like below:
select * from func()
DEMO
Conclusion
You can not use variable in normal SQL statement in Postgres.
You have to use any Procedural Language i.e. plpgsql to use variable.
DO Block doesn't return any value so you can not use select statement like above in DO block. It is good for non-returning queries i.e. insert, update, delete or grant etc.
Only way to return a value from procedural language code block is - you have to wrap it in a suitable PostgreSQL Function.
So I have a function in PostgreSQL that dynamically selects columns from a dynamic table. I got this solution from this post and it works great other than one thing.
This is inside of a file that is connected to a Node server, and so the $1 and $2 in the second SELECT * FROM represent values passed from there. The issue right now is that I am getting a syntax error that I don't understand (I am newer to SQL so that may be why).
$2 represents the name of the table to be selected from as a string, so for example it could be 'goals'. The error is syntax error at or near "'goals'". I realize that it cannot be a string with single quotes (I believe) and so I am wondering how to convert that variable to be a table name? using "goals" there as well as goals, for example works as expected, though I'm not sure how to do that outside of a function.
CREATE OR REPLACE FUNCTION get_data(user_id INT, table_name anyelement)
RETURNS SETOF ANYELEMENT AS $$
BEGIN
RETURN QUERY EXECUTE
format('SELECT * FROM %s WHERE user_id = $1', pg_typeof(table_name)) USING user_id;
END;
$$ LANGUAGE plpgsql;
SELECT * FROM get_data($1, NULL::$2);
$1 is 5 and $2 is 'goals' for example
After many hours of trying to figure it out, thanks to Adrian's comment, I found MassiveJS (how I'm connecting to my PostgreSQL server) has inline functions to do queries. In my controller file in my server I was able to create a one line function as such:
const data = await db[tableName].where("user_id=$1", [userId])
Didn't know inline SQL existed in MassiveJS, so that was great to find out!
For the below code which is in SQL server needs to be converted into PostgresSQL. I did try the same way we do in SQL Server but it dint work.
declare #ID table (ID int)
insert into MyTable(ID)
output inserted.ID into #ID
values (1)
So the above code works well in SQL server but when it comes to Postgres it does not work.
Can someone help in converting this code to Postgres ? Also can someone help me in getting a sample SP with inout and out parms in Postgres please.
Assuming this is part of a stored function (or procedure) written in PL/pgSQL, you can use the returning clause as documented in the manual:
....
declare
l_generated_id int;
begin
...
insert into my_table(id)
values (1)
returning id into l_generated_id;
...
end;
But I have to admit that this seems rather unnecessary as the inserted value is hardcoded in the INSERT statement
this is my exam
DO $$DECLARE
oldName varchar :='old';
newName varchar := 'new';
BEGIN
....
END$$;
If I run this script get this:
ERROR: syntax error at or near "DO"
LINE 1: DO $$ DECLARE
^
What I did wrong?
I'd say you are using PostgreSQL 8.4 or older, which does not support DO blocks. You will need to either upgrade, or use CREATE OR REPLACE FUNCTION to create a PL/PgSQL function, then SELECT function_name() to call it.
Always specify your PostgreSQL version in questions.
How do I execute an SQL string statement in DB2? I'm using IBM Data Studio.
Do you mean executing a dynamic SQL string? Something like:
DECLARE stmt VARCHAR(1000);
DECLARE my_table VARCHAR(50);
SET my_table = 'DEPT_'||deptNumber;
SET stmt = 'SELECT * FROM '||my_table;
PREPARE s1 FROM stmt;
EXECUTE s1;
You can only do that in a stored proc though. One defined as CREATE PROCEDURE GetDeptInfo (deptNumber VARCHAR(5)) for this example. Read about EXECUTE and PREPARE in the db2 docs http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/index.jsp
After days of researching I found how to write and run dynamic SQL on DB2:
create or replace procedure Search ()
BEGIN
DECLARE v_dynamicSql varchar(2000);
SET v_dynamicSql = 'INSERT INTO dictonary(name) values(' || 'dynamicSQL in db2' ||')';
EXECUTE IMMEDIATE v_dynamicSql;
END;
Hope to help someone.
What difficulty are you encountering?
There are likely lots of ways to do it. Here's one:
File -> New -> Other -> SQL or XQuery script
You may need to create a project or define a database connection.
Enter the SQL code.
Script -> Run script.
Results will show up at the bottom of your screen.
In Control Center, right click the database, you will see "Query". Click on it and you are good to go.