Informix SELECT INTO syntax error - sql

I've been trying to use code which finds the count of elements in a table and stores it in a local variable. I basically just want to check the existence of a record, so if there is any easier way to do this.
Here is an example I found of storing the result of a query in a variable (link):
CREATE FUNCTION checklist( d SMALLINT )
RETURNING VARCHAR(30), VARCHAR(12), INTEGER;
DEFINE name VARCHAR(30);
DEFINE dept VARCHAR(12);
DEFINE num INTEGER;
SELECT mgr_name, department,
CARDINALITY(direct_reports)
FROM manager INTO name, dept, num
WHERE dept_no = d;
IF num > 20 THEN
EXECUTE FUNCTION add_mgr(dept);
ELIF num = 0 THEN
EXECUTE FUNCTION del_mgr(dept);
ELSE
RETURN name, dept, num;
END IF;
END FUNCTION;
But when I try to create my own version of this, I get a syntax error. I have no idea what the problem is.
CREATE FUNCTION test ()
RETURNING INTEGER AS num1;
DEFINE l_count INTEGER;
CREATE TEMP TABLE t_queued_calls (
session_id DEC(18,0) PRIMARY KEY,
calling_number NVARCHAR(50)
) WITH NO LOG;
INSERT INTO t_queued_calls VALUES (123456, '5555555555');
SELECT COUNT(*) FROM t_queued_calls INTO l_count WHERE session_id = 123456;
DROP TABLE t_queued_calls;
END FUNCTION;

The position of the INTO clause is wrong in both functions. The INTO clause goes after the select-list (the list of expressions after the keyword SELECT) and before the FROM clause (see the Informix "Guide to SQL: Syntax" manual on the SELECT statement), as in this code:
CREATE PROCEDURE test()
RETURNING INTEGER AS num1;
DEFINE l_count INTEGER;
CREATE TEMP TABLE t_queued_calls (
session_id DEC(18,0) PRIMARY KEY,
calling_number NVARCHAR(50)
) WITH NO LOG;
INSERT INTO t_queued_calls VALUES (123456, '5555555555');
SELECT COUNT(*) INTO l_count FROM t_queued_calls WHERE session_id = 123456;
DROP TABLE t_queued_calls;
RETURN l_count;
END PROCEDURE;
Also, the first function as shown in the question has the same problem with the ordering of the clauses. Also, it does not always RETURN a value, and the original version of the second function never returns a value (although it says it will).

The could be related to the fact the insert dont have the columns name
adapt your_column1, your_column2 to your table schema
INSERT INTO t_queued_calls (your_column1, your_column2) VALUES (123456, '5555555555');
SELECT COUNT(*) FROM t_queued_calls INTO l_count WHERE session_id = 123456;
And/Or the number of column from the select don't match the number and type in insertt ... you select un field only but insert two field
and select into is strange select format ...normally is insert into but select don't use into clause

I found the correct syntax from this question: [Use MERGE statement in a stored procedure with Informix
SELECT COUNT(*) INTO l_count FROM t_queued_calls WHERE session_id = 123456;

Related

Table Variable and Table-Valued Function equivalent in PostgreSQL

I need to create a function in PostgreSQL for the following :
Query multiple tables based on a business logic (all result sets return the same type of data)
Compile all result sets into one table and return that table
Is it possible to accomplish this without using the temp tables in PostgreSQL?
I currently do this in Microsoft SQL server using Table Variables, below is a sample function:
create FUNCTION test(#search_in nvarchar(500))
RETURNS #data_table TABLE
(
item_id int,
item_type nvarchar(1),
first_name nvarchar(100),
last_name nvarchar(100))
) AS
BEGIN
-- from first table
if charindex('search_in_authors', #search_in) > 0
insert into #data_table
select item_id, 'a', first_name, last_name
from authors
where first_name = 'james'
-- from second table
if charindex('search_in_editors', #search_in) > 0
insert into #data_table
select item_id, 'e', first_name, last_name
from editors
where first_name = 'james'
-- from third table
if charindex('search_in_publishers', #search_in) > 0
insert into #data_table
select item_id, 'p', first_name, last_name
from publishes
where first_name = 'james'
-- there could be more like these based on the business logic...
(...)
-- finally return the records compiled in #data_table
RETURN
END
Sample calls to the function:
select * from dbo.test('search_in_authors')
select * from dbo.test('search_in_authors, search_in_editors')
select * from dbo.test('search_in_authors, search_in_editors,search_in_publishers ')
Are there any options in PostgreSQL to achieve this other than using a temp table ?
Thanks,
San
You can use RETURN QUERY to add the result of various queries to the output.
CREATE OR REPLACE FUNCTION public.testf()
RETURNS TABLE(id INTEGER, name text)
STABLE
AS $$
DECLARE
BEGIN
RETURN QUERY select 1 as id, 'abc' as name;
RETURN QUERY select 2 as id, 'def' as name;
RETURN QUERY select 3 as id, 'xyz' as name;
-- Final return as set is now complete.
return;
END;
$$ LANGUAGE plpgsql;
select * from public.testf();
id | name
----+------
1 | abc
2 | def
3 | xyz
(3 rows)

Unable to call for procedure

When I try to call the procedure with call insertp_detail ('P005','02','T001','CAT2') , it will show the error :
SQL0811N The result of a scalar fullselect, SELECT INTO statement, or
VALUES INTO statement is more than one row. SQLSTATE=21000
The expected result that I want with this procedure is to insert the values into purchase_detail table.
CREATE PROCEDURE insertp_detail
(IN purchase_id char(4), seat_id char(2), trans_id char(4), seat_type varchar(5))
BEGIN
IF ((SELECT COUNT(trans_id)
FROM purchase_detail
GROUP BY trans_id) < 3)
THEN INSERT into purchase_detail values(purchase_id, seat_id, trans_id, seat_type);
end if;
end
This is correct. You have a group by which generally returns multiple rows. Presumably you intend to count the number of rows only for the trans_id provided as an argument to the stored procedure:
CREATE PROCEDURE insertp_detail (
IN in_purchase_id char(4),
IN in_seat_id char(2),
IN in_trans_id char(4),
IN in_seat_type varchar(5)
)
BEGIN
IF ((SELECT COUNT(*)
FROM purchase_detail
WHERE pd.trans_id = in_trans_id
) < 3)
THEN
INSERT INTO purchase_detail
VALUES (in_purchase_id, in_seat_id, in_trans_id, in_seat_type);
END IF;
END;
Note that the parameters to the stored procedure have prefixes to distinguish them from column names.
You should also list the columns for purchase_detail for the INSERT statement.

PL/SQL - putting line while records are both found and not found

I am trying to write small PL/SQL block which runs a tiny query inside. Problem is that I don't want to see whole data returned by query but to see whether something exists or not. My block looks like this:
procedure check_data as
table_data varchar2;
BEGIN
SELECT * into table_data FROM (
with temp_table as ( select a_number, a_group, a_date from table1
where a_id in (15)
)
SELECT b_city, b_district, b_nationality, b_age
FROM table2 JOIN temp_table ON a_id=b_id
WHERE b_age>=10
and b_age<23
ORDER BY b_nationality DESC);
IF SQL%FOUND THEN
raise_application_error(-20001,'OK, found something')
else DBMS_OUTPUT.PUT_LINE ('found nothing!');
end if;
end;
Generally struggling with declaring temp_table (I get PLS-00201: identifier 'table_data' must be declared) and putting results on screen.
I'll be grateful for any tips.
Try this now:
create table table1( a_id number,a_number number, a_group varchar(10), a_date date)
create table table2 (b_id number,b_city varchar(10), b_district varchar(10), b_nationality varchar(10), b_age number)
create or replace procedure check_data as
table_data varchar2(100);
BEGIN
SELECT *
into table_data
FROM (
with temp_table as ( select a_id, a_number, a_group, a_date
from table1
where a_id in (15)
)
SELECT 1
FROM table2
JOIN temp_table ON a_id = b_id
WHERE b_age>=10
and b_age<23
ORDER BY b_nationality DESC)
where rownum < 2 ;
IF SQL%FOUND THEN
raise_application_error(-20001,'OK, found something');
Else
DBMS_OUTPUT.PUT_LINE ('found nothing!');
End if;
end;
Its working fine and compiled well. Now implement the expert suggestion to get it working fine. I am not looking into your logic. I just get your code compiled.

How to return PK from insert query?

I have a postgresql table with sequence:
CREATE TABLE A (
id integer NOT NULL DEFAULT nextval('a_seq'::regclass),
X integer,
Y integer,
Z boolean default false,
CONSTRAINT A_pkey PRIMARY KEY (id)
)
I have an insert statment in function as follows:
insert into A(x,y) select $1,getdig();
i want this insert to return the id the row was given to a function varabile called A_id
It should be something like:
CREATE OR REPLACE FUNCTION bbb(m integer)
RETURNS integer AS
$BODY$
declare
A_id int;
begin
insert into A(x,y) select $1,getdig() RETURNING id into A_id;
actions using A_id like:
update A set z=True where id=A_id;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
How do I do that?
There is no need for the select:
CREATE OR REPLACE FUNCTION bbb(m integer)
RETURNS integer AS
$BODY$
declare
A_id int;
begin
insert into A(x,y)
values ($1,getdig())
RETURNING id into A_id;
-- actions using A_id like:
update A set z=True where id=A_id;
return a_id; -- don't forget to return something!
end;
$BODY$
LANGUAGE plpgsql VOLATILE
You use the returning clause:
with i as (
insert into A(x,y)
select $1, getdig()
returning id
)
select *
from i;
Technically, the CTE is not necessary. But I prefer that queries that return values start with SELECT.

Insert another parameter along with table type

The table tblEffort has 3 columns EmployeeName, Effort, Date. I get the first 2 column values from a table type parameter and have to insert a common date for all these values.
do not have the option to include timesheetdate in dtCSV
There should be some other way than running an update again on the inserted columns right?
The below code gives the error - Must declare the table variable "#TimesheetDate"
CREATE TYPE dbo.SaveEffort_TableType AS TABLE
(
EmployeeName varchar(200),
Effort decimal(18,2)
);
GO
CREATE PROCEDURE SaveEmployeeEffort
(
#TimesheetDate datetime,
#dtCSV AS dbo.SaveEffort_TableType readonly
)
AS
BEGIN
INSERT INTO tblEffort(EmployeeName,Effort,[Date])
SELECT * FROM #dtCSV,#TimesheetDate
END
You need to put the variable into the SELECT clause, not the FROM clause
CREATE PROCEDURE SaveEmployeeEffort
(
#TimesheetDate datetime,
#dtCSV AS dbo.SaveEffort_TableType readonly
)
AS
BEGIN
INSERT INTO tblEffort(EmployeeName,Effort,[Date])
SELECT EmployeeName,Effort, #TimesheetDate FROM #dtCSV
END