Snowflake case when statement not working using args - python

I am trying to make the select statement dependent on an args variable I am passing via a python script (in this case args.type='hello').
It looks like this:
case when '{{type}}' = 'hello'
then
SELECT
name from table1
else
SELECT
city from table2 where code='usa'
end
The error I am getting:
syntax error unexpected 'case'.
syntax error unexpected 'else'.
syntax error unexpected ')'.
I also tried IFF clause but did run into same issues.

If you were sending this sql to snowflake and it was failing due to a syntax error, I would expect you to get an error like "SQL compilation error: ...". Therefore I wonder if the issue isn't in your python program.
Could you share more?

Where you trying to set some paramters?
The snowflake python connector supports several syntaxes:
format: .execute("... WHERE my_column = %s", (value,))
pyformat: .execute("... WHERE my_column = %(name)s", {"name": value})
qmark: .execute("... WHERE my_column = ?", (value,))
numeric: .execute("... WHERE my_column = :1", (value,))
If you are using python3 you can use something like f" {pythonvar} ".
Could you give us more context about what you are doing?

Related

Using the return values from one SQL statement in another SQL statement using SQL Magic in a Jupyter Notebook

I am working on a Jupyter Notebook on some standard DB2 table functions. I'd like to be able to refer to values returned from one SQL statement in other SQL statements. The syntax of the variable reference is getting me here. This is the code I use to get the values I want to use in later statements:
mgd_baseline = %sql select float(rows_read) rows_read \
, float(rows_returned) rows_returned \
from table(mon_get_database(-2)) as mgd
Then I would like to use it like this:
if mgd_baseline[0].rows_read > 0 or mgd_baseline[0].rows_returned > 0:
%sql select decimal((float(rows_read)-:mgd_baseline[0].rows_read/(float(rows_returned)-:mgd_baseline[0].rows_returned),10,0) read_eff \
from table(mon_get_database(-2)) as mgd
But that fails with this error message:
(ibm_db_dbi.ProgrammingError) ibm_db_dbi::ProgrammingError: SQLNumResultCols failed: [IBM][CLI Driver][DB2/NT64] SQL0104N An unexpected token "," was found following "-?[0].rows_returned)". Expected tokens may include: ")". SQLSTATE=42601\r SQLCODE=-104 [SQL: 'select decimal((float(rows_read)-?[0].rows_read/(float(rows_returned)-?[0].rows_returned),10,0) read_eff from table(mon_get_database(-2)) as mgd'] [parameters: ([(61959.0, 3219.0)], [(61959.0, 3219.0)])]
It looks to me like the sql magic is not passing on the value the way I would expect it to. It looks like it is considering the end of the host variable name the opening square bracket. I am not familiar enough with python to know what notation I can use to make it work.
I know I can do this as a workaround:
if mgd_baseline[0].rows_read > 0 or mgd_baseline[0].rows_returned > 0:
bl_rows_read=mgd_baseline[0].rows_read
bl_rows_returned=mgd_baseline[0].rows_returned
read_eff=%sql select decimal((float(rows_read)-:bl_rows_read)/(float(rows_returned)-:bl_rows_returned),16,2) read_eff \
from table(mon_get_database(-2)) as mgd
Due to some future plans, I would prefer to not have to do the additional assignment.
Is there any way to use those values (mgd_baseline[0].rows_read, mgd_baseline[0].rows_returned) directly in my sql magic sql statement without reassigning them?
I figured it out. It's not using host variables (generic compilation with different values for better package cache use), but for this particular application I don't particularly care if they're treated as host variables. Here is what works:
if mgd_baseline[0].rows_read > 0 or mgd_baseline[0].rows_written > 0:
read_eff=%sql select decimal((float(rows_read)-{mgd_baseline[0].rows_read})/(float(rows_returned)-{mgd_baseline[0].rows_returned}),16,2) read_eff \
from table(mon_get_database(-2)) as mgd

PyQt SQL Query with Bindings

I'm trying to write an SQL query in PyQt5 that updates some data in a table, but cannot get the query to work. I've read countless forums but as far as I can tell my code is correct. I also have read the documentation back to front so maybe I'm missing something?
I am using PyQt5, python3.5 and SQLITE. The following code (lastError/lastQuery not shown):
self.sqlWrite('ct','MarkerSize',123)
def sqlWrite(self,tbl,var,val):
query = QtSql.QSqlQuery(self.db) # First create query instance.
# Prepare query with placeholders, then bind values.
query.prepare('UPDATE :tbl SET value=:val WHERE property=:var')
query.bindValue(0,tbl)
query.bindValue(1,val)
query.bindValue(2,var)
# Finally execute query.
query.exec_()
...produces the error:
near "?": syntax error Unable to execute statement
near "?": syntax error Unable to execute statement
UPDATE :tbl SET value=:val WHERE property=:var
Parameter count mismatch
Have I lost the plot? What am I missing?
Thanks in advance.
A table name is not a parameter, so you cannot bind a value to it. Placeholders are intended for use with literal values, not arbitrary strings. For the latter, you should just use normal string interpolation:
query.prepare('UPDATE "%s" SET value=:val WHERE property=:var' % tbl)
query.bindValue(':val', val)
query.bindValue(':var', var)
For a more generic way to escape identifiers, use the query's driver:
tbl = query.driver().escapeIdentifier(tbl, QSqlDriver.TableName)
query.prepare('UPDATE %s SET value=:val WHERE property=:var' % tbl)

Django: Using named parameters on a raw SQL query

I'm trying to execute a raw query that is built dynamically.
To assure that the parameters are inserted in the valid position I'm using named parameters.
This seems to work for Sqlite without any problems. (all my tests succeed)
But when I'm running the same code against MariaDB it fails...
A simple example query:
SELECT u.*
FROM users_gigyauser AS u
WHERE u.email like :u_email
GROUP BY u.id
ORDER BY u.last_login DESC
LIMIT 60 OFFSET 0
Parameters are:
{'u_email': '%test%'}
The error I get is a default syntax error as the parameter is not replaced.
I tried using '%' as an indicator, but this resulted in SQL trying to parse
%u[_email]
and that returned a type error.
I'm executing the query like this:
raw_queryset = GigyaUser.objects.raw(
self.sql_fetch, self._query_object['params']
)
Or when counting:
cursor.execute(self.sql_count, self._query_object['params'])
Both give the same error on MariaDB but work on Sqlite (using the ':' indicator)
Now, what am I missing?
edit:
The format needs to have s suffix as following:
%(u_email)s
If you are using SQLite3, for some reason syntax %(name)s will not work.
You have to use :name syntax instead if you want to pass your params as {"name":"value"} dictionary.
It's contrary to the documentation, that states the first syntax should work with all DB engines.
Heres the source of the issue:
https://code.djangoproject.com/ticket/10070#comment:18

Python - MySQL - Unknown columns 'http://www.......................' in 'field list'

I'm trying to select a record from my MySQL db, the problem is that it returns with this error which i don't understand, i searched on the web for a solution, and there are many similar cases, but none apply to this specific one.
The expression i'm trying to execute is the following:
result = cursor.execute("""select * from urls where domain = '%s';"""%(found_url,))
it is in a try clause and it always goes right to the except giving me this error:
OperationalError(1054, "Unknown column 'http://..................' in 'field list'")
(i omitted the url, the dots act as placeholders)
after some cycles, being in a loop, it stops giving me that error and changes it to this:
ProgrammingError(2014, "Commands out of sync; you can't run this command now")
any idea? i'm going crazy on this one.
Use query parameters instead of how you are doing it with string interpolation. The protects you against SQL Injection attacks.
cursor.execute("""select * from urls where domain = %s""", (found_url,))
Notice the differences here:
The %s is NOT quoted, as the MySQLdb library will handle this automatically
You are not using string interpolation (no % after the string to replace your placeholders). Instead, you are passing a tuple as the second argument to the execute function.
Since you are only using one place holder and you still need to pass a tuple, there is a comma to indicate it is a tuple (found_url,)

SQLite syntax error, but SQL string works manually (python)

My programme raises an sqlite3.OperationalError exception with the following message:
: near ",": syntax error
I have a try-except block that prints me the SQL string.:
try:
self._db_cur.execute(sql)
except Exception, e:
print sql
raise e
This is the printed SQL... the most interesting part is... that if I insert that query in my SQLite manager... it DOES work. I'm clueless here.
INSERT INTO connections_to_jjos(
connections_id,
jjo_error_id,
binder_task_id
)
VALUES
(
55,
(select id from jjo_errors where name = "--Unknown--"),
(select id from tasks where name = "DCDD")
)
,
(
55,
(select id from jjo_errors where name = "--Unknown--"),
(select id from tasks where name = "ANDD")
)
For some reasons, I am not using parameterized statements, if it helps...
This is probably a bug* in sqlite3.
While this test code works fine with python3.3 and sqlite 3.7.15.2, it fails with sqlite 3.7.3.
That means it should be fixed in newer versions, so you'd need to update your sqlite version (or python) to make it work, or work around this by not using multiple values sets.
*edit: actually not a bug, just a feature that was only introduced in version 3.7.11

Categories

Resources