Julia ReadOnlyMemoryError with ODBC SQL query - sql

I'm working on writing a function that queries a SQL database and I'm encountering a ReadOnlyMemoryError() that has me stumped. The issue is that when I run my code as a simple script everything functions as expected. But when I try to wrap the exact same code in a function I get the ReadOnlyMemoryError().
Here's the script version of my code:
using ODBC
using DBInterface
using Dates
using DataFrames
server = "server string "
username = "username "
password = " password"
db = " db name"
start_date=Nothing
end_date=Nothing
if start_date == Nothing || typeof(start_date) != "Date"
start_date = Dates.today() - Dates.Day(30)
end
if end_date == Nothing || typeof(end_date) != "Date"
end_date = Dates.today()
end
query = """ SQL SELECT statement """
connect_string = "DRIVER={ODBC Driver 17 for SQL Server};SERVER=" * server *
";DATABASE=" * db *
";UID=" * username *
";PWD=" * password
conn = ODBC.Connection(connect_string)
df = DBInterface.execute(conn, query) |> DataFrame
This works as expected, the result is a dataframe df with about 500k rows. However, when I try use this same code to make a reusable function I get the error:
using ODBC
using DBInterface
using Dates
using DataFrames
function get_cf_data(start_date=Nothing, end_date=Nothing)
server = " server string "
username = " user name"
password = " password"
db = " db "
if start_date == Nothing || typeof(start_date) != "Date"
start_date = Dates.today() - Dates.Day(30)
end
if end_date == Nothing || typeof(end_date) != "Date"
end_date = Dates.today()
end
query = """ SQL SELECT statement """
connect_string = "DRIVER={ODBC Driver 17 for SQL Server};SERVER=" * server *
";DATABASE=" * db *
";UID=" * username *
";PWD=" * password
conn = ODBC.Connection(connect_string)
df = DBInterface.execute(conn, query) |> DataFrame
return df
end
In this case, when I try to call from REPL get_cf_data() I get ERROR: ReadOnlyMemoryError(). I'm somewhat new to Julia, so any insight would be very much appreciated. Thank you!

As commented, best practice in most programming languages when integrating APIs like ODBC connections is to close and release its resource after usage.
Additionally, consider parameterization (best practice in any language running SQL that passes literal values) where you set up a prepared SQL statement and bind values in a subsequent execute call.
function get_cf_data(start_date=Nothing, end_date=Nothing)
server = " server string "
username = " user name"
password = " password"
db = " db "
if isnothing(start_date) || typeof(start_date) != "Date"
start_date = Dates.today() - Dates.Day(30)
end
if isnothing(end_date) || typeof(end_date) != "Date"
end_date = Dates.today()
end
# PREPARED STATEMENT WITH QMARK PLACEHOLDERS
sql = """SELECT Col1, Col2, Col3, ...
FROM myTable
WHERE myDate BETWEEN ? AND ?
"""
connect_string = "DRIVER={ODBC Driver 17 for SQL Server};SERVER=" * server *
";DATABASE=" * db *
";UID=" * username *
";PWD=" * password
conn = ODBC.Connection(connect_string)
# PREPARE STATEMENT AND BIND PARAMS
stmt = DBInterface.prepare(conn, sql)
df = DBInterface.execute(stmt, (start_date, end_date)) |> DataFrame
DBInterface.close(stmt) # CLOSE STATEMENT
DBInterface.close(conn) # CLOSE CONNECTION
stmt = Nothing; conn = Nothing # UNINTIALIZE OBJECTS
return df
end

Related

Go over a simple quote in a Where of a SQL query

I have a SQL query where I have to pass a string in my where, my string can have a simple quote in the name of the program and at the same time break the string and create an error in my request.
Yes I would just like to skip the code, but the actual logic has been done so that we are able to modify the code, so I can't just trust that.
Here is the query in my ASP.NET MVC 5 project:
IQueryable<ListeProgrammesCol> query = db.Database.SqlQuery<ListeProgrammesCol>(
"SELECT id AS offreID, nomProgramme AS nom, codeProgramme AS code, dateAjout, dateLastUpdate, gestionEnLigne " +
"FROM tbl_offreCol " +
"WHERE FK_etablissement = " + instId +" AND offreType = 3 AND archive = 0 AND codeProgramme = '" + code + "' AND nomProgramme = '" + progNom + "' " +
"ORDER BY nomProgramme").AsQueryable();
And here is the query if you want to text in SQL Server Management Studio:
SELECT
id AS offreID, nomProgramme AS nom, codeProgramme AS code,
dateAjout, dateLastUpdate, gestionEnLigne
FROM
tbl_offreCol
WHERE
FK_etablissement = 923000
AND offreType = 3
AND archive = 0
AND codeProgramme = '351.A0'
AND nomProgramme = 'RAC en Techniques d'éducation spécialisée'
ORDER BY
nomProgramme
This is the problem: d'éducation
//////UPDATE
I decided to use linq to make my request, so I no longer need to use quotes. Here is the query:
var query = (from oc in db.tbl_offreCol
where oc.FK_etablissement == instId
&& oc.offreType == 3
&& oc.archive == 0
&& oc.codeProgramme == code
&& oc.nomProgramme == progNom
select new ListeProgrammesCol
{
offreID = oc.id,
nom = oc.nomProgramme,
code = oc.codeProgramme,
dateAjout = oc.dateAjout,
dateLastUpdate = oc.dateLastUpdate,
gestionEnLigne = oc.gestionEnLigne
}).OrderBy(x => x.nom).AsQueryable();

Talend - Read a SQL from .txt and pass variables to it

I need to read an Excel file and excecute a different SQL Query (Oracle) for each row of the Excel, depending on the value that a column ("tipo") of the table has. Also, I need to pass variables to the SQL query that comes from others columns of the same excel.
I have accomplished this with a tjava, creating a string that generates de query.. somthing like this (simplified):
String var1 = input_row.var1;
String var2 = input_row.var2;
String sql_query = ""
if (tipo.toString().equals(String.valueOf("Option1"))) {
query_ev = "select " + var1 + " as variable1, " + var2 + " as var 2 from dual";}
if (tipo.toString().equals(String.valueOf("Option2"))) {
query_ev = "select " + var1+ " from dual";}
context.sql = sql_query;
Nevertheless, my "problem" is that my queries are long, and this method only allows me to put them in the tjava whithout line breaks, so its very difficult to edit them since they remain a "one-row-query" in the tjava.
Is there a way to accomplish the same but having the queries formatted ?
for example, for Option1 having this
select " + var1 + " as variable1, " + var2 + " as var 2
from dual
where
...
I appreciate any clue.
Try this:
query_ev = "select "
" + var1 + " as variable1, " + var2 + " as var 2 "+
from dual";
I am without Java right now to verify but I think this approach could help formatting. Just check that you have enough spaces - don't do this
"as var 2"+"from dual"
which would result in SQL like
"as var 2from dual"

How to pass a date variable to an SQL query in Python

Python3.5
Sql Server 2012 Standard
package is pypyodbc
This Code Works
myConnection = pypyodbc.connect('Driver={SQL Server};'
'Server=myserver;'
'Database=mydatabase;'
'TrustedConnection=yes')
myCursor = myConnection.cursor()
sqlstr = ("Select * From DB.Table1 Where DB.Table1.Date <= '7/21/2016'")
myCursor.execute(sqlstr)
results = myCursor.fetchall()
However, Date must be a variable passed in by users. I made several mods to sqlstr but continue to error on myCursor.execute: "TypeError: bytes or integer address expected instead of tuple instance"
sqlstr = ("Select * From DB.Table1 Where DB.Table1.Date <= %s", '7/21/2016')
Error
sqlstr = ("Select * From DB.Table1 Where DB.Table1.Date <= '%s'", '7/21/2016')
Error
sqlstr = ("Select * From DB.Table1 Where DB.Table1.Date <= ?", "'7/21/2016'")
Error
var1 = "'7/21/2016'"
sqlstr = ("Select * From DB.Table1 Where DB.Table1.Date <= %s", var1)
and several more. However, I am sure there is one correct way...
Thanks for any help!
I am sure there is one correct way
Yes, it's a parameterized query:
date_var = datetime(2016, 7, 21)
sql = """\
SELECT [ID], [LastName], [DOB] FROM [Clients] WHERE [DOB]<?
"""
params = [date_var] # list of parameter values
crsr.execute(sql, params)
for row in crsr.fetchall():
print(row)

Upper Function Input parameter in Oracle

I try to prevent SQL injection in SQL query. I used following code to do it but unfortunately I faced some problem. The query is not running in oracle DB:
strQuery = #"SELECT PASSWORD FROM IBK_USERS where upper(user_id) =upper(:UserPrefix) AND user_suffix=:UserSufix AND STATUS_CODE='1'";
//strQuery = #"SELECT PASSWORD FROM IBK_CO_USERS where user_id = '" + UserPrefix + "' AND user_suffix='" + UserSufix + "' AND STATUS_CODE='1'";
try
{
ocommand = new OracleCommand();
if (db.GetConnection().State == ConnectionState.Open)
{
ocommand.CommandText = strQuery;
ocommand.Connection = db.GetConnection();
ocommand.Parameters.Add(":UserSufix", OracleDbType.Varchar2,ParameterDirection.Input);
ocommand.Parameters[":UserSufix"].Value = UserSufix;
ocommand.Parameters.Add(":UserPrefix", OracleDbType.Varchar2,ParameterDirection.Input);
ocommand.Parameters[":UserPrefix"].Value = UserPrefix.ToUpper();
odatareader = ocommand.ExecuteReader();
odatareader.Read();
if (odatareader.HasRows)
{
Your parameters shouldn't contain the semicolon :. This is just an indicator in your query that the variable that follows is a parameter, but you don't have to supply that on the .NET side:
ocommand.Parameters["UserSufix"] = ...

How to pass arguments to a function to connect to database

I would like to create a function to connect to a SQLite database by passing it two parameters: database name and table.
I tried this:
sqLiteConnect <- function(database, table) {
con <- dbConnect("SQLite", dbname = database)
query <- dbSendQuery(con, "SELECT * FROM ", table)
fetch(query, n = -1)
}
But I pass result <- sqLiteConnect(primary_database, "table_name") I get Error in sqliteExecStatement(conn, statement, ...) : RS-DBI driver: (error in statement: near " ": syntax error)
If I change my function to
sqLiteConnect <- function(database, table) {
con <- dbConnect("SQLite", dbname = database)
query <- dbSendQuery(con, "SELECT * FROM ", table, "")
fetch(query, n = -1)
}
I get Error in sqliteExecStatement(conn, statement, ...) : unused argument ("")
I guess the problem is in concatenating a variable to a string.
dbSendQuery requires the SQL statement as a single character string (it does not take the table as an argument), so you would need to create it using either paste() or sprintf(), for example:
sqLiteConnect <- function(database, table) {
con <- dbConnect("SQLite", dbname = database)
query <- dbSendQuery(con, paste("SELECT * FROM ", table, ";", sep=""))
fetch(query, n = -1)
}