SQLAlchemy get output parameters from a postgresql stored procedure - stored-procedures

I am using Postgresql9.2 and SQLAlchemy0.8 . I have a stored procedure in database which has many out parameters and i want them to use by dot notation. But so far I have failed miserably. Below is how my code looks like.
An example to show what i am doing is as follows.
CREATE OR REPLACE FUNCTION stored_proc_name(IN in_user_id bigint, IN in_amount bigint,
OUT pout_one bigint, OUT pout_two bigint )
RETURNS record AS
$BODY$
begin
select count(*) as AliasOne into pout_one from tabe_names where conditions;
select user_name as AliasTwo into pout_two from table_name where condition;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION stored_proc_name(bigint, bigint)
OWNER TO postgres;
My code snippet is as following:
#session object from sessionmaker
result_obj = session.execute(func.stored_proc_name(user_id, amount))
print result_obj.fetechall()
#The above print statement prints following on the console.
>> [('(1,100)',)]
Clearly the above result fetches string. What I want is something like result_obj.pout_one and use it in my code.
Is there any way of achieving it. A working code snippet will be highly appreciated.
Thanks a lot!

You could try something like this:
query = select([column('pout_one'), column('pout_two')],
from_obj=[func.stored_proc_name(user_id, amount)])
session.execute(query)
The inspiration for this is from the SQLAlchemy list where someone asked a similar question. This could result in the desired output (I can't test it right now).

Related

How to pass a table name as a parameter in BigQuery procedure?

I am trying to build bigquery stored procedure where I need to pass the table name as a parameter. My code is:
CREATE OR REPLACE PROCEDURE `MKT_DS.PXV2DWY_CREATE_PROPERTY_FEATURES` (table_name STRING)
BEGIN
----step 1
CREATE OR REPLACE TABLE `MKT_DS.PXV2DWY_CREATE_PROPERTY_FEATURES_01` AS
SELECT DISTINCT XX.HH_ID, A.ECR_PRTY_ID, XX.ANCHOR_DT
FROM table_name XX
LEFT JOIN
(
SELECT DISTINCT HH_ID, ECR_PRTY_ID
FROM `analytics-mkt-cleanroom.Master.EDW_ECR_ECR_MAPPING`
WHERE HH_ID NOT LIKE 'U%'
AND ECR_PRTY_ID IS NOT NULL
)A
ON XX.HH_ID = A.HH_ID----one (HH) to many (ecr)
;
END;
CALL MKT_DS.PXV2DWY_CREATE_PROPERTY_FEATURES(`analytics-mkt-cleanroom.MKT_DS.Home_Services_Multi_Class_Aesthetic_Baseline_Final_Training_Sample`);
I followed a couple of similar questions here and here, tried writing an EXECUTE IMMEDIATE version of the above but not able to work out the right syntax.
I think issue is; the SELECT statement in my code is selecting multiple columns XX.HH_ID, A.ECR_PRTY_ID, XX.ANCHOR_DT and the EXECUTIVE IMMEDIATE setup is meant to work only for one column. But I'm not sure. Please advise. Thank you.
I am basically trying to write stored procedures for data pipeline building.
Hope below is helpful.
pass a parameter as a string.
CALL MKT_DS.PXV2DWY_CREATE_PROPERTY_FEATURES(`analytics-mkt-cleanroom.MKT_DS.Home_Services_Multi_Class_Aesthetic_Baseline_Final_Training_Sample`);
-->
CALL MKT_DS.PXV2DWY_CREATE_PROPERTY_FEATURES('analytics-mkt-cleanroom.MKT_DS.Home_Services_Multi_Class_Aesthetic_Baseline_Final_Training_Sample');
use EXECUTE IMMEDIATE since a table name can't be parameterized as a variable in a query.
----step 1
EXECUTE IMMEDIATE FORMAT("""
CREATE OR REPLACE TABLE `MKT_DS.PXV2DWY_CREATE_PROPERTY_FEATURES_01` AS
SELECT DISTINCT XX.HH_ID, A.ECR_PRTY_ID, XX.ANCHOR_DT
FROM `%s` XX
LEFT JOIN
(
SELECT DISTINCT HH_ID, ECR_PRTY_ID
FROM `analytics-mkt-cleanroom.Master.EDW_ECR_ECR_MAPPING`
WHERE HH_ID NOT LIKE 'U%%'
AND ECR_PRTY_ID IS NOT NULL
)A
ON XX.HH_ID = A.HH_ID----one (HH) to many (ecr)
;
""", table_name);
escape % in a format string with additional %
LIKE 'U%'
-->
LIKE 'U%%'
see PARSE_DATE not working in FORMAT() in BigQuery

Is it possible to pass in a variable amount of parameters to a stored procedure in redshift?

I am trying to write a stored procedure in AWS Redshift SQL and one of my parameters needs the possibility to have an integer list (will be using 'IN(0,100,200,...)' inside there WHERE clause). How would I write the input parameter in the header of the procedure so that this is possible (if at all?)
I've tried passing them in as a VARCHAR "integer list" type thing but wasn't sure then how to parse that back into ints.
Update: I found a way to parse the string and loop through it using the SPLIT_PART function and store all of those into a table. Then just use a SELECT * FROM table with the IN() call
What I ended up doing was as follows. I took in the integers that I was expecting as a comma-separated string. I then ran the following on it.
CREATE OR REPLACE PROCEDURE test_string_to_int(VARCHAR)
AS $$
DECLARE
split_me ALIAS FOR $1;
loop_var INT;
BEGIN
DROP TABLE IF EXISTS int_list;
CREATE TEMPORARY TABLE int_list (
integer_to_store INT
);
FOR loop_var IN 1..(REGEXP_COUNT(split_me,',') + 1) LOOP
INSERT INTO int_list VALUES (CAST(SPLIT_PART(split_me,',',loop_var) AS INT));
END LOOP;
END;
$$ LANGUAGE plpgsql;
So I would call the procedure with something like:
CALL test_string_to_int('1,2,3');
and could do a select statement on it to see all the values stored into the table. Then in my queries the need this parameter I ran:
.........................
WHERE num_items IN(SELECT integer_to_store FROM int_list);

stored procedure functions not working properly?

i am writing a procedure function in phpmyadmin for attendance purpose.But i am getting wrong information from function if condition.
below is the sample code for procedure and functions without if.
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `USP_GetEmployeeAttendanceReport`(IN selectedIndex int,IN searchText nvarchar(20),IN selectedDate datetime)
BEGIN
select FN_CheckEmpAttendanceStatus(selectedIndex,selectedDate);
END
Function FN_CheckEmpAttendanceStatus
DELIMITER $$
CREATE DEFINER=`root`#`localhost` FUNCTION `FN_CheckEmpAttendanceStatus`(cardid varchar(150),selectedDate datetime) RETURNS int(11)
BEGIN
DECLARE result INT;
set result=(select count(*) from iotrans where CARDID=cardid and dt=selectedDate);
return result;
END
but from function i am getting garbage values (i.e 80,0,81,82....).thanks in advance
The problem is most likely caused by the fact that you use the same name cardid for a function parameter as for a column in iotrans, thus MySQL can't tell them apart and condition WHERE CARDID=cardid always evaluates as TRUE.
Always give distinct names to routine parameters. I'd suggest to come up with some naming scheme, e.g. putting a underscore in front of the name of a parameter, so that you do that consistently across all your code and can easily tell whether it's a parameter or a column name.
One more thing usage of result variable is unnecessary overhead in your case as is BEGIN...END block.
That being said your function might've looked like this
CREATE DEFINER=`root`#`localhost`
FUNCTION FN_CheckEmpAttendanceStatus
(
_cardid varchar(150),
_selectedDate datetime
) RETURNS INT(11)
RETURN
(
SELECT COUNT(*)
FROM iotrans
WHERE cardid = _cardid
AND dt = _selectedDate
);

Conditionally inserting from a stored procedure

I am trying to teach myself SQL. I have a web matrix project I am working on to edit and display posts backed by a SQL server Datatabase. A work colleague suggested I use a Stored Procedure to commit the post rather than writing the sql inline.
So far the procedure looks ok but I would like to check if the url slug already exists, and if so return something to say so (The url slug should be unique). I'm struggling with how I am supposed to check before the insert. I have also read that it is bad practice to return from a stored procedure, but I thought it would be a good idea to return something to let the caller know the insert did not go ahead.
Any help would be very much appreciated.
-- =============================================
-- Author: Dean McDonnell
-- Create date: 05/12/2011
-- Description: Commits an article to the database.
-- =============================================
CREATE PROCEDURE CommitPost
#UrlSlug VARCHAR(100),
#Heading VARCHAR(100),
#SubHeading VARCHAR(300),
#Body VARCHAR(MAX)
AS
INSERT INTO Posts(UrlSlug, Heading, SubHeading, Body, Timestamp)
VALUES(#UrlSlug, #Heading, #SubHeading, #Body, GETDATE())
This is what I have so far.
CREATE PROCEDURE CommitPost
#UrlSlug VARCHAR(100),
#Heading VARCHAR(100),
#SubHeading VARCHAR(300),
#Body VARCHAR(MAX)
AS
IF NOT EXISTS (SELECT * FROM Posts WHERE UrlSlug = #UrlSlug)
INSERT INTO Posts(UrlSlug, Heading, SubHeading, Body, Timestamp)
VALUES(#UrlSlug, #Heading, #SubHeading, #Body, GETDATE())
SELECT ##ROWCOUNT
To check for existance, do a SELECT COUNT like so:
CREATE PROCEDURE CommitPost
#UrlSlug VARCHAR(100),
#Heading VARCHAR(100),
#SubHeading VARCHAR(300),
#Body VARCHAR(MAX)
AS
DECLARE #count INT
SELECT #count = COUNT(*) FROM Posts WHERE UrlSlug = #UrlSlug
IF #count = 0 THEN
BEGIN
INSERT INTO Posts(UrlSlug, Heading, SubHeading, Body, Timestamp)
VALUES(#UrlSlug, #Heading, #SubHeading, #Body, GETDATE())
END
You may set an unique index on UrlSlug to make the database reject insertions of urls already in the database, but nonetheless you should check before inserting.
If your caller wants to know if the row was inserted, return the #count value. If it's 0 then the line was inserted, else not. I'm not aware of a "bad practice" regarding to return values from a SP. As a SP does not have a result, though, you need to use an out parameter.
If you do just one SQL statement like this insert you could just use paratemerized query i.e. I assume that you are using .NET.
If you want to return values I would suggest that you use a FUNCTION instead of a STORED PROCEDURE. You can return either tables or whatever you want from a function.
There are some limitations though. You can dig a little deeper into the differences to see what is used when. Here's a link that can help you out get started:
Function vs. Stored Procedure in SQL Server
If you want to use stored procedure anyway, you can either return a single row, single column result set, using SELECT, or just use an output parameter.
If you want to do actions depending of whether the column exists or not I would suggest that you look into MERGE statement.That way you would perform only one query to the database instead of two or more(doing SELECT and then INSERT).
There are also other ways to use database access like various ORMs on top of the database in the code that will make your life easier, like LINQ-to-SQL etc. There are a lot of possibilities out there. You need to determine what's best in a given situation.

How to submit the query by stored procedure in MySQL?

Hello I am trying to automate my history tracking procedure in MySQL.
The procedure should update a table and create another using uid as a name.
CREATE PROCEDURE `InsertQueryStore`( u VARCHAR(128), ID INT, q VARCHAR(1024) )
BEGIN
INSERT INTO querystore(`qID`, `qstring`, `user`) VALUES(ID, q, u); # this works
# DROP TABLE IF EXIST ID ; //Can I do something like this?
# CREATE TABLE ID q; // The q is a query string which should return results into to table ID
END;
then I would like to call as:
Call InsertQueryStore("myname", 100, "select * from mydb.table limit 10")
What is the proper way to use the varchar variable in the procedure?
Thank you beforehand.
Arman.
I think the way to go with that would be using Dynamic SQL.
MySQL does not support dynamic SQL in the way some DBMS do, but it does have the PREPARE/EXECUTE methods for creating a query and executing it. See if you can use them within your stored procedure.
Something like:
CREATE PROCEDURE `InsertQueryStore`( u VARCHAR(128), ID INT, q VARCHAR(1024) )
BEGIN
INSERT INTO querystore(`qID`, `qstring`, `user`) VALUES(ID, q, u);
PREPARE stmt FROM "DROP TABLE IF EXIST ?";
EXECUTE stmt USING ID;
DEALLOCATE PREPARE stmt;
/* etc */
END;
If you find you can't use the parameterised version with '?' in that context, just use CONCAT() to assemble it with the actual value in the string as it is already known at that stage.
There is a reasonable article about it here, mentioned in a previous SO post.

Resources