hey there -

took a quick look and we don't support anything with variable declarations, 
multiple statements in a single string, or multiple result sets.  All of that 
is outside of SQLAlchemy expression languages scope.

Since what you're doing is extremely specific to a certain database, if your 
approach works what is the problem you are seeking to solve ?



On Mon, Nov 30, 2020, at 10:03 AM, Paul Harrington wrote:
> Hello Community!
> I have not posted here for several years as I have been getting along just 
> fine with the excellent SQLAlchemy toolkit and the excellent documentation. 
> However, I am trying to do something a bit fancy since all the SQL Server 
> dataservers I use are running versions that support OPENJSON. A number of our 
> applications have used staging techniques to copy tables of data to the 
> dataserver so that that can be used in JOINs (e.g. send up 10,000 identifiers 
> into the table rather than doing RBAR or batching into IN clauses). This 
> technique is IO intensive and has quite a bit of overhead. An alternative 
> approach is to serialize the data into a big blob of JSON, send it over as a 
> single scalar and then expand it out to a table via a CTE on the dataserver. 
> We have found the performance of this to be excellent from scripting 
> language, presumably because we are avoiding so many API calls. However, I 
> have not found a way to do this cleanly from SQLAlchemy and end up using 
> sql.text a lot. Also, because it does not seem possible to re-use the same 
> placeholder multiple times in a statement, if we want to expand out the JSON 
> multiple times (e.g. if the JSON is nested and has multiple tables in it), we 
> work around that using [sys].[sp_executesql]. Please see snippet below and a 
> complete script (with create_engine redacted) attached.
> 
> What I am looking for is some guidance on how to use SQLALchemy to produce 
> CTEs that reference the same variable (@blob_o_json) multiple times without 
> having to pass in the same value multiple times.
> 
> thanks in advance!
> pjjH
> 
> 
> 
> *# **TODO**: formulate this as a SQLAlchemy expression (is there an exec() 
> element?)*
> outer_sql = r'''
> EXEC [sys].[sp_executesql] @statement = :sql,
>                            @params = N'@bind_value_blob_o_json varchar(max)',
>                            @bind_value_blob_o_json = :json_blob
> '''
> 
> *# we prepare the *outer* statement that has a single command in it*
> statement = sql.text(outer_sql)
> 
> *# now execute that passing in unicode value of the inner SQL.*
> 
> logging.basicConfig(format='%(asctime)s %(message)s')
> logging.getLogger().setLevel(logging.DEBUG)
> nrows = [1000,10000,100000, 200000, 500000]
> for n in nrows:
>     *# we cons up a list of dicts to represent a single 'inline' table with 
> lots of rows*
>     logging.debug("passing  %d items" % (n))
>     blob_o_json =json.dumps([dict(rn=x,foo=x*2,bar=x-1,fruit='banana', 
> flavor='yummy') for x in *range*(0,n)])
>     *# Note: we named arguments in this next line correspond to the :sql and 
> :json_blob placeholders in outer_sql*
>     result =  engine.execute(statement,sql=six.text_type(inner_sql), 
> json_blob=blob_o_json)
>     rs = result.fetchall()
>     *#logging.debug((len(rs), rs[]))*
>     *# drop down to DBAPI to process each result-set. The application should 
> know how many result-sets will be present*
>     *# I think it is likely that the vast majority of queries will just have 
> a single result-set*
> 
>     *# I did not know how to get to anything other than the first result-set 
> ... I thought there *
>     *# was probably some pyodbc magic to  make it work with SQLAlchemy and -- 
> sure enough! -- there*
>     *# was a ticket with a workaround: 
> https://github.com/sqlalchemy/sqlalchemy/issues/1635#issuecomment-441907416*
> 
>     *#cursor = result.cursor*
>     *#rs1 = cursor.fetchall()*
>     *#cursor.nextset()*
>     *#rs2 = cursor.fetchall()*
> 
>     *#logging.debug((len(rs1), rs1[-4:], rs2[-4:]))*
>     logging.debug("finished %d" % (n))
> 
> logging.debug("done")
> 

> -- 
> SQLAlchemy - 
> The Python SQL Toolkit and Object Relational Mapper
>  
> http://www.sqlalchemy.org/
>  
> To post example code, please provide an MCVE: Minimal, Complete, and 
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
> description.
> --- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/345f67ce-a4b9-4575-87bc-81653868908en%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/sqlalchemy/345f67ce-a4b9-4575-87bc-81653868908en%40googlegroups.com?utm_medium=email&utm_source=footer>.
> 
> 
> *Attachments:*
>  * sqlalchemy_execute_sql_demo.py

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/a94c8509-4019-47ac-98b9-893b8ba9974a%40www.fastmail.com.

Reply via email to