PostgreSQL Select INTO with CASE statement - postgresql

I have an Employee table with column - Id, FirstName, isGlobal, Age. I am writing below SQL to check if the Employee already exists in DB or not. I want to store the Id and isGlobal into variable for further processing in my stored function.
SELECT Id, CASE WHEN (isGlobal IS NULL) THEN 1 ELSE 0 END
INTO o_NameId, o_IsGlobal
FROM Employee
WHERE firstName='test';
On running this SQL, it gives me syntax error.
ERROR: syntax error at or near ","
LINE 2: INTO o_NameId, o_IsGlobal
^
SQL state: 42601
What's wrong with my SQL?
Any help would be greatly appreciated.

looks like o_NameId and o_IsGlobal are not declared,
try:
DO
$$
DECLARE
o_NameId int;
o_IsGlobal int;
BEGIN
SELECT Id, CASE WHEN (isGlobal IS NULL) THEN 1 ELSE 0 END
INTO o_NameId, o_IsGlobal
FROM Employee
WHERE firstName='test';
END
$$;
also try to follow SQL name convention like:
SQL keywords: UPPER CASE
names (identifiers) lower_case_with_underscores List item

Related

Unable to return a table using CTE in postgresql

I am trying to create a CTE which establishes a parent child relationship and return the ids of the required childs. The Childs can also be the parent of their respective children. I have tried writing a postgresql function for that but I am facing an error, for which I am not able to understand the cause. Might be a very silly reason or syntax error, so far I have no clue. The error is 'ERROR: syntax error at or near "return"
LINE 22: return query
^
SQL state: 42601
Character: 472'
create or replace function fn_Get_All_Child_For_Process(
client_id integer,process_id integer,level integer)
returns table (id integer)
language 'plpgsql'
as
$$
begin
WITH CTE_Child AS
(
SELECT Id,level,ParentId
FROM ClientProcesses
WHERE ID = process_id and ClientId=client_id and Level < level
UNION ALL
SELECT t.Id,t.level,t.ParentId
FROM ClientProcesses t,CTE_Child C
where t.ParentID = C.ID and t.Level < level and t.ClientId=client_id
)
return query
SELECT C.Id FROM CTE_Child C where C.Id not in (process_id) ;
end;
$$;

Number of returned columns does not match expected column count // Return concatinated row in plpgsql function

I'm trying to create query: searching stats of persons by phone number.
I start using INNER JOIN in internal query and now i don't understand how type i must return.
I'm trying to use view as type, but they cant contain atributes with same name. Okay, i trim it to 3.
But i still get error and dont understand what it means:
ERROR: structure of query does not match function result type
DETAIL: Number of returned columns (3) does not match expected column count (2).
CONTEXT: PL/pgSQL function get_fio_by_phone_number(bigint) line 3 at RETURN QUERY
SQL state: 42804
Code:
CREATE OR REPLACE VIEW persons_fios_and_telephons AS
SELECT p.name, p.surname, pt.number
FROM person p
INNER JOIN persons_telefons pt on p.id = pt.person_id;
DROP FUNCTION get_fio_by_phone_number(bigint);
CREATE OR REPLACE FUNCTION get_fio_by_phone_number(user_phone BIGINT) RETURNS SETOF persons_and_telephons
AS $$
BEGIN
RETURN QUERY
SELECT *
FROM persons_fios_and_telephons pat
WHERE pat.number = get_fio_by_phone_number.user_phone;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE EXCEPTION 'There is no person with number "%".', user_phone;
END;
$$ LANGUAGE plpgsql;
SELECT * FROM get_fio_by_phone_number(89998887766)
Is there any way to make function without rough atributes enumeration? Thanks!

Postgresql function table name parameter

I have n tables sharing a least one column name ("Date"), I want to create a function which can make a
select column1, column2, ..., columnx from myfunction('table_name','date_value')
First, tried with just table name parameter (excerpt from another post on this website) :
CREATE OR REPLACE FUNCTION test(_tbl regclass, OUT result integer) AS
$func$
BEGIN
EXECUTE format('SELECT (EXISTS (SELECT FROM %s))::int', _tbl)
INTO result;
END
$func$ LANGUAGE plpgsql;
and called with SELECT test('"vDxi"'); but the result is :
ERROR: syntax error at or near "FROM"
LINE 1: SELECT (EXISTS (SELECT FROM "vDxi"))::int
^
QUERY: SELECT (EXISTS (SELECT FROM "vDxi"))::int
CONTEXT: PL/pgSQL function test(regclass) line 3 at EXECUTE statement
SQL state: 42601
Since I'm a real newbie in PLSQL, I don't know where the error is (tried a SELECT * ... with no success).
And the calling query does not permit me to select column names, if I can make it working...

Select query by declare variable on postgresql

I am new working postgresql and pgadmin4.I write a very simple query.
I have a table called PgFinalLocationsTable on public schema.In my table there are a few filed.One of these filed is UserName .I want to declare a variable and finally do select on my table according this variable like below:
DO $$
DECLARE myvar text default 'sa';
BEGIN
select * from public."PgFinalLocationsTable" where "UserName" = myvar;
END $$;
But why i got these message:
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
SQL state: 42601
It is a simple query!!!
After googling and see post on stack i have changed my query like this:
CREATE OR REPLACE FUNCTION fun(text myvar) RETURNS text AS $$
--DECLARE myvar text;
BEGIN
select * from public."PgFinalLocationsTable" where "UserName" = myvar;
END;
$$ language plpgsql;
select fun('sa');
I want to return all my fields and i do not want to use plpgsql.I want to use PostgreSQL. In any case i got this error:
ERROR: type myvar does not exist
SQL state: 42704
What is the problem on my first query and second query?Should i have make a function for select query when i want to pass a variable?
I do all stuff because i want to create this sql query:
"IF (NOT EXISTS(SELECT 1 FROM [dbo].[{0}] WHERE [UserId] = #UserId And [DeviceId] = #DeviceId)) " +
"BEGIN " +
"INSERT INTO [dbo].[{0}]([Id], [Location], [Timestamp], [UserId], [DeviceId], [AllowDomains], [Topic], [UserName], [FirstName], [LastName], [JobLocationName], [LocationId], [AppVersion], [AppName]) " +
"VALUES(#Id, GEOGRAPHY::Point(#X, #Y, 4326), #Timestamp, #UserId, #DeviceId, #AllowDomains, #Topic, #UserName, #FirstName, #LastName, #JobLocationName, #LocationId, #AppVersion, #AppName) " +
"END "
You don't understand to DO command well. DO command is anonymous function without declaration, and because it has not declared an output, then is not possible any other result than debug stream.
so your first example has not sense in PostgreSQL. Result of unbind queries in MSSQL is returned as result of MS SQL procedure. Nothing similar is possible in PostgreSQL. PostgreSQL knows only functions, that can returns scalar value, composite value or relation (only one). When you are coming from MS SQL, the best what you can, try to forgot almost all knowleadge from MS SQL.
ERROR: type myvar does not exist
SQL state: 42704
This bug is clean - you switch variable name and type name - really type myvar doesn't exist.
Some function that returns table can looks like:
CREATE OR REPLACE FUNCTION fx1(myvar text)
RETURNS SETOF public."PgFinalLocationsTable" AS $$
BEGIN
RETURN QUERY SELECT * FROM public."PgFinalLocationsTable" WHERE "UserName" = myvar;
END;
$$ LANGUAGE plpgsql;
or you can use a SQL language only
CREATE OR REPLACE FUNCTION fx1(myvar text)
RETURNS SETOF public."PgFinalLocationsTable" AS $$
SELECT * FROM public."PgFinalLocationsTable" WHERE "UserName" = $1;
$$ LANGUAGE sql;
Because PostgreSQL doesn't support unbind queries, then doesn't allow it. You should to use RETURN QUERY command - in PLpgSQL language.
Because programming with stored procedures is really different between PostgreSQL and MSSQL (MSSQL is not similar to any other), please, try to read documentation - it is not bad https://www.postgresql.org/docs/current/static/plpgsql.html
Your function can looks in Postgres like (I don't know used types)
CREATE OR REPLACE FUNCTION fx("_UserId" int,
"_DeviceId" int,
"_X" int,
"_Y" int,
...
BEGIN
IF NOT EXISTS(SELECT * FROM /* I don't know what [{0}] means */
WHERE "UserId" = "_UserId" AND "DeviceId" = "_DeviceId")
THEN
INSERT INTO ..
END IF;
END;
$$ LANGUAGE plpgsql;
Probably your fragment can be solved without procedural extension by INSERT INTO ON CONFLICT DO NOTHING command https://www.postgresql.org/docs/current/static/sql-insert.html - what is better.
Note - using case sensitive identifiers is short way to hell.

Using IF Exists function in postgreSQL pgadmin3 (syntax error ,SQL state: 42601 Character: 1)

I am trying to execute an SQL statement in pgadmin3 that do the following:
If a student with a specific name and age already exists then get the student_id else insert a new record with the specified name and age and then get the created student_id
I have tried this code:
IF EXISTS (SELECT 1 FROM main.student WHERE studentname='hhh' and studentage=15)
BEGIN
SELECT student_id FROM main.student WHERE studentname='hhh' and studentage=15
END
ELSE
BEGIN
INSERT INTO main.student(studentname,studentage) VALUES('hhh',15)
END;
END IF;
But I am always getting this error:
syntax error at or near "IF"
SQL state: 42601
Character: 1
Can you please tell me what I am doing wrong. Also how can I get the student_id after the insert statement?
Actually your statement is not SQL. it is PL/PGSQL statement.
So obviously when you send this to Postgres as SQL query it will throw an exception.
If you are doing this from pgAdmin3 it has nice feature to run pl/psql scripts. use it
IF EXISTS (SELECT 1 FROM main.student WHERE studentname='hhh' and studentage=15) THEN
SELECT student_id FROM main.student WHERE studentname='hhh' and studentage=15;
ELSE
INSERT INTO main.student(studentname,studentage) VALUES('hhh',15);
END IF;
Some points you need to consider:
For IF statement, you need to use THEN
To run just one syntax, you don't need the BEGIN/END
Use ; at the end of each statement
Also if you are running an ad-hoc statement, you need to run it within DO command
DO
$do$
IF EXISTS (SELECT 1 FROM main.student WHERE studentname='hhh' and studentage=15) THEN
SELECT student_id FROM main.student WHERE studentname='hhh' and studentage=15;
ELSE
INSERT INTO main.student(studentname,studentage) VALUES('hhh',15);
END IF;
END
$do$
For the last part of your question, you can return the id you are inserting
INSERT INTO main.student(studentname,studentage) VALUES('hhh',15) RETURNING student_id