Pass UUID value as a parameter to the function - postgresql

I have the table with some columns:
--table
create table testz
(
ID uuid,
name text
);
Note: I want to insert ID values by passing as a parameter to the function. Because I am generating the ID value
in the front end by using uuid_generate_v4(). So I need to pass the generated value to the function to insert
into the table
My bad try:
--function
CREATE OR REPLACE FUNCTION testz
(
p_id varchar(50),
p_name text
)
RETURNS VOID AS
$BODY$
BEGIN
INSERT INTO testz values(p_id,p_name);
END;
$BODY$
LANGUAGE PLPGSQL;
--EXECUTE FUNCTION
SELECT testz('24f9aa53-e15c-4813-8ec3-ede1495e05f1','Abc');
Getting an error:
ERROR: column "id" is of type uuid but expression is of type character varying
LINE 1: INSERT INTO testz values(p_id,p_name)

You need a simple cast to make sure PostgreSQL understands, what you want to insert:
INSERT INTO testz values(p_id::uuid, p_name); -- or: CAST(p_id AS uuid)
Or (preferably) you need a function, with exact parameter types, like:
CREATE OR REPLACE FUNCTION testz(p_id uuid, p_name text)
RETURNS VOID AS
$BODY$
BEGIN
INSERT INTO testz values(p_id, p_name);
END;
$BODY$
LANGUAGE PLPGSQL;
With this, a cast may be needed at the calling side (but PostgreSQL usually do better automatic casts with function arguments than inside INSERT statements).
SQLFiddle
If your function is that simple, you can use SQL functions too:
CREATE OR REPLACE FUNCTION testz(uuid, text) RETURNS VOID
LANGUAGE SQL AS 'INSERT INTO testz values($1, $2)';

Related

Error while creating table : Syntax error at or near "#"

I am trying to convert SQL Server stored function to PostgreSQL stored function I am getting one syntactical error at declare #table1 table
CREATE OR REPLACE FUNCTION ETL_GetBuildingDetailsByUserID ( p_nInstID numeric=0)
RETURNS Boolean
AS $$
declare #table1 table
(
nbuilding numeric(18, 0) NOT NULL,
sbuild_name varchar(50) NULL,
sclient_build_id varchar(50) NULL,
nbuilding_inst_id numeric(18, 0) NOT NULL,
ntemp_building_id numeric(18,0) NULL,
nno_of_floors numeric(18,0) NULL
)
declare v_strDeptIds text;
v_strSubDeptIds text;
BEGIN
v_strsql := 'SELECT building.*
FROM building
WHERE (building.nbuilding_inst_id = '|| cast(p_nInstID as varchar(1)) ||')
';
print v_strsql
v_strsql1 text;
v_strsql1 := v_strsql
Insert into #table1; execute sp_executesql; v_strsql1
select * from #table1;
Return true;
END;
$$ LANGUAGE plpgsql;
Error
ERROR: syntax error at or near "#"
LINE 4: declare #table1 table
Can any one please tell what I am doing wrong?
It seems your function actually returns the result of a SELECT query, not a boolean value, so returns boolean is wrong to begin with.
To return a result, you need to declare the function as returns table(). But as you seem to simply return rows from the building table you can define it as returns setof building.
Then remove the useless dynamic SQL which seems completely unnecessary.
In PL/pgSQL there are no table variables, and copying the result of a query into one before returning that result from that table seems to be an unnecessary step which only slows down things. In Postgres you simply return the result of the query, there is no need to store it locally.
Additionally: rather than casting a parameter to another type inside the function it's better to declare that parameter with the type you expect.
So the simplified version of that function in PostgreSQL would be:
CREATE OR REPLACE FUNCTION ETL_GetBuildingDetailsByUserID ( p_nInstID text)
RETURNS setof building
AS $$
select building.*
from building
WHERE building.nbuilding_inst_id = p_nInstID
$$ LANGUAGE sql;
You can use it like this:
select *
from ETL_GetBuildingDetailsByUserID ('42');
Unrelated, but: using numeric(18,0) for columns that store values without decimals is overkill. You should define those columns as bigint. Much faster and uses less space than numeric.

Insert within function fails with "query has no destination for result data"

Here is the complete example code:
CREATE TABLE testtbl (
id integer NOT NULL,
intval integer,
strval varchar(64)
);
CREATE SEQUENCE testtbl_id_seq
START WITH 1 INCREMENT BY 1
NO MINVALUE NO MAXVALUE CACHE 1;
ALTER SEQUENCE testtbl_id_seq OWNED BY testtbl.id;
ALTER TABLE ONLY testtbl ALTER COLUMN id SET DEFAULT
nextval('testtbl_id_seq'::regclass);
ALTER TABLE ONLY testtbl ADD CONSTRAINT testtbl_pkey PRIMARY KEY (id);
CREATE FUNCTION insert_testtbl (p_intval integer, p_strval varchar(64))
RETURNS integer AS $$
DECLARE
v_new_id integer;
BEGIN
INSERT INTO testtbl (intval, strval) VALUES (p_intval, p_strval)
RETURNING v_new_id;
RETURN v_new_id;
END;
$$ LANGUAGE plpgsql;
SELECT insert_testtbl(1, 'One');
When I run this (PostgreSQL version is 9.6.1), I get:
ERROR: query has no destination for result data
CONTEXT: PL/pgSQL function insert_testtbl(integer,character varying) line 5 at SQL statement
This doesn't make sense; I AM specifying a destination for the result!
What am I doing wrong here? Thanks!!!
I am specifying a destination for the result!
No you are not.
RETURNING v_new_id; simply means:
"return the current value of the variable v_new_id from this insert statement"
(which is null as the variable was never assigned a value)
You are not storing the generated value anywhere.
You either need to use an into clause:
CREATE FUNCTION insert_testtbl (p_intval integer, p_strval varchar(64))
RETURNS integer AS $$
DECLARE
v_new_id integer;
BEGIN
INSERT INTO testtbl (intval, strval) VALUES (p_intval, p_strval)
RETURNING id
INTO v_new_id; --<<< HERE
RETURN v_new_id;
END;
$$ LANGUAGE plpgsql;
Or convert everything it simple SQL function:
CREATE FUNCTION insert_testtbl (p_intval integer, p_strval varchar(64))
RETURNS integer AS
$$
INSERT INTO testtbl (intval, strval) VALUES (p_intval, p_strval)
RETURNING id;
$$ LANGUAGE sql;

Rename the column name of a stored function

I've got a postgresql stored procedure, which is returning an integer.
When I call that function, the result is returned with the function name as column name.
For example the name of the function is: "add-person". The column name, when invoking the function, is "add-person".
Is there a way to make the database return the integer with a self-choosen column name? For example "id"?
I think it is pretty easy, but I currently miss the forests for the trees..
Edit:
What i'd missed to tell, is that the return value is a variable, like so:
CREATE OR REPLACE FUNCTION "scheme"."add-person"(arggivenname character varying, argfamilyname character varying) RETURNS integer AS
$BODY$
DECLARE
varResponse integer;
BEGIN
-- Operations before
INSERT INTO "scheme"."table"
(
given_name,
family_name
)
VALUES
(
arggivenname,
argfamilyname
)
RETURNING
"id"
INTO
varResponse;
-- Operations after
RETURN varResponse;
END;
$BODY$
LANGUAGE plpgsql VOLATILE COST 100;
You can us the AS statement for that. That means:
Select add-person() AS yourcolumnname
To have a named column from a function it is necessary to create a type and return that type from the function
create type mytype as (mycolumn integer);
create or replace function ri()
returns mytype as $$
select 1;
$$ language sql;
select * from ri();
mycolumn
----------
1
Edit
Or much simpler without the type creation as in #pozs comment:
create or replace function ri(out mycolumn integer)
as $$
select 1;
$$ language sql;

PL/Proxy returning Unsupported Type on Stored Procedure Call

I've setup a Stored Procedure in PL/Proxy to make a query, and receive some RECORDs back.
In PL/Proxy:
CREATE OR REPLACE FUNCTION query_autocomplete(q text, i_id bigint)
RETURNS SETOF RECORD AS $$
CLUSTER 'autocompletecluster';
RUN ON i_id;
$$ LANGUAGE plproxy;
In each Partition:
CREATE OR REPLACE FUNCTION query_autocomplete(q text, i_id bigint)
RETURNS SETOF RECORD AS $$
DECLARE
rec RECORD;
BEGIN
FOR rec IN EXECUTE q
LOOP
RETURN NEXT rec;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
As you've likely guessed, this is hitting a defined SERVER in PGSQL called 'autocompletecluster'. The query string that I'm sending through is as follows:
$sql = "SELECT * FROM autocomplete WHERE member_id = :memberId";
$query = $this->db->prepare("SELECT query_autocomplete('{$sql}',1234");
It's returning the following:
SQLSTATE[XX000]: Internal error: 7 ERROR: PL/Proxy function public.query_autocomplete(0): unsupported type
The table that query is hitting is defined as such:
CREATE TABLE autocomplete (
id character varying(100) NOT NULL,
extra_data hstore,
username character varying(254),
member_id bigint
);
What am I doing wrong?
The error strongly suggests that PL/Proxy doesn't support SETOF RECORD. Try instead defining your functions to return autocomplete%rowtype or, failing that, RETURNS TABLE (...) with a matching columns-set.

Returning from a function with OUT parameter

I have an error, but I don't know what the problem is.
I want execute a function and return a value from a column filled in by the column default, a sequence - the equivalent of currval(sequence).
I use:
PostgreSQL 9.0
pgAdmin III
CREATE OR REPLACE FUNCTION name_function(in param_1 character varying
, out param_2 bigint)
AS
$$
BEGIN
INSERT INTO table (collumn_seq,param_1) VALUES (DEFAULT,param_1)
returning collumn_seq;
--where:collumn_seq reference a collumn serial..
END;
$$
LANGUAGE plpgsql VOLATILE;
I can create the function without error but when trying to execute, the following error is returned:
SELECT name_function('GHGHGH');
ERROR: The query has no destination for result data
It would work like this:
CREATE OR REPLACE FUNCTION name_function(param_1 varchar
, OUT param_2 bigint)
LANGUAGE plpgsql AS
$func$
BEGIN
INSERT INTO table (collumn_seq, param_1) -- "param_1" also the column name?
VALUES (DEFAULT, param_1)
RETURNING collumn_seq
INTO param2;
END
$func$;
Normally, you would add a RETURN statement, but with OUT parameters, this is optional.
Refer to the manual for more details:
Returning from a function
Executing a Query with a Single-row Result
The simple case can be covered with a plain SQL function.
And you can omit the target column that shall get its DEFAULT value.
And you can just as well use a RETURNS clause in this case:
CREATE OR REPLACE FUNCTION name_function(param_1 varchar)
RETURNS bigint
LANGUAGE sql AS
$func$
INSERT INTO table (param_1) -- "param_1" also the column name?
VALUES (param_1)
RETURNING collumn_seq;
$func$;