I am trying to INSERT some data into a table that has been created in SQL Azure.
SQL Structure
Field 1 DATE
Field 2 INT
Field 3 INT
Python code used:
#I know I have connected to the correct database.
Connection = pyodbc.connect(conn.conn())
cursor = Connection.cursor()
SQLCommand = ('INSERT INTO table_name ([Field 1], [Field 2], [Field 3]) VALUES ('31-Dec-14', 1, 2);')
cursor.execute(SQLCommand)
Connection.commit()
I get the following error
pyodbc.ProgrammingError: ('42S22', "[42S22] [Microsoft][SQL Server Native Client 11.0][SQL Server]Invalid column name '31-DEC-2014'. (207)
If I replace it with
SQLCommand = ('INSERT INTO table_name ([Field 1], [Field 2], [Field 3]) VALUES (?, ?, ?);', ('31-DEC-2014',1,2))
cursor.execute(SQLCommand)
Connection.commit()
I get the following error
TypeError: The first argument to execute must be a string or unicode query.
How should I input dates and integers into an SQL azure table via python?
Thanks
Thanks for the question.
I highly recommend you use pymssql if you are trying to connect to Azure SQL DB using Python.
Coming to your question, it depends on what the datetime format is used when you create your SQL table.
Here is how you would insert dates and integers using pymssql against the AdventureWorks schema(AdventureWorks schema is a pre loaded schema that you can create your database with for testing).
import pymssql
conn = pymssql.connect(server='yourserver.database.windows.net', user='yourusername#yourserver', password='yourpassword', database='AdventureWorks')
cursor = conn.cursor()
cursor.execute("INSERT SalesLT.Product (Name, ProductNumber, StandardCost, ListPrice, SellStartDate) OUTPUT INSERTED.ProductID VALUES ('SQL Server Express', 'SQLEXPRESS', 0, 0, CURRENT_TIMESTAMP)")
row = cursor.fetchone()
while row:
print "Inserted Product ID : " +str(row[0])
row = cursor.fetchone()
If you have questions about how to install pymssql on your machine, here is some reference documentation that will help you :)
- Windows
- Mac
- Linux
If you have any issues with using pymssql with Azure SQL DB do let me know as I would love to help.
Best,
Meet Bhagdev
Program Manager, Microsoft
The date parser does not like your format. See the Microsoft documentation for a list of valid formats
The following syntax should work:
SQLCommand = ("INSERT INTO table_name ([Field 1], [Field 2], [Field 3]) VALUES ('2014-12-31', 1, 2);")
cursor.execute(SQLCommand)
Connection.commit()
Related
I have installed teradatasql python module recently.When I am doing batch insert into table it is not throwing duplicate error in the script, Else it is skipping that insert statement. Table has first column as UNIQUE in teradata table. But I want it to throw an error in the code.
with teradatasql.connect ('{"host":"whomooz","user":"guest","password":"please"}') as con:
with con.cursor () as cur:
cur.fast_executemany=True
cur.execute ("insert into voltab (?, ?)", [
[1, "abc"],
[2, "def"],
[3, "ghi"]])
You need to use the escape functions teradata_nativesql and teradata_get_errors to obtain errors for unique column violations.
This example Python script:
import teradatasql
with teradatasql.connect (host="whomooz", user="guest", password="please") as con:
with con.cursor () as cur:
cur.execute ("create volatile table voltab (c1 integer unique not null, c2 varchar(10)) on commit preserve rows")
sInsert = "insert into voltab (?, ?)"
cur.execute (sInsert, [[123, "abc"], [123, "def"]])
cur.execute ("{fn teradata_nativesql}{fn teradata_get_errors}" + sInsert)
print (cur.fetchone () [0])
Prints the following output:
[Version 17.20.0.14] [Session 1080] [Teradata Database] [Error 2801] Batch request failed to execute 1 of 2 batched statements. Batched statement 2 failed to execute because of Teradata Database error 2801, Duplicate unique prime key error in guest.voltab.
at gosqldriver/teradatasql.formatError ErrorUtil.go:89
at gosqldriver/teradatasql.(*teradataConnection).formatDatabaseError ErrorUtil.go:217
...
I want to execute a command using pyodbc in my Django app. When I do simple update with one column it works great:
cursor.execute("UPDATE dbo.Table SET attr = 1 WHERE id = {}".format(id))
However when I try to use a string as a column value it throws error:
cursor.execute("UPDATE dbo.Table SET attr = 1, user = '{}' WHERE id = {}".format(id, str(request.user.username)))
Here's error message:
('42S22', "[42S22] [Microsoft][ODBC SQL Server Driver][SQL Server]Invalid column name 'Admin'. (207) (SQLExecDirectW)")
Suprisingly this method works:
cursor.execute("UPDATE dbo.Table SET attr = 1, user = 'Admin' WHERE id = {}".format(id))
What seems to be the problem? Why is sql mistaking column value for its name?
As mentioned above, you have your arguments backwards, but if you're going to use cursor.execute(), the far more important thing to do is use positional parameters (%s). This will pass the SQL and values separately to the database backend, and protect you from SQL injection:
from django.db import connection
cursor = connection.cursor()
cursor.execute("""
UPDATE dbo.Table
SET attr = 1,
user = %s
WHERE id = %s
""", [
request.user.username,
id,
])
You've got your format arguments backwards. You're passing id to user, and username to the id WHERE clause.
I'd like to use the IN clause with a prepared Oracle statement using cx_Oracle in Python.
E.g. query - select name from employee where id in ('101', '102', '103')
On python side, I have a list [101, 102, 103] which I converted to a string like this ('101', '102', '103') and used the following code in python -
import cx_Oracle
ids = [101, 102, 103]
ALL_IDS = "('{0}')".format("','".join(map(str, ids)))
conn = cx_Oracle.connect('username', 'pass', 'schema')
cursor = conn.cursor()
results = cursor.execute('select name from employee where id in :id_list', id_list=ALL_IDS)
names = [x[0] for x in cursor.description]
rows = results.fetchall()
This doesn't work. Am I doing something wrong?
This concept is not supported by Oracle -- and you are definitely not the first person to try this approach either! You must either:
create separate bind variables for each in value -- something that is fairly easy and straightforward to do in Python
create a subquery using the cast operator on Oracle types as is shown in this post: https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::p11_question_id:210612357425
use a stored procedure to accept the array and perform multiple queries directly within PL/SQL
or do something else entirely!
Just transform your list into a tuple and format the sql string with it
ids = [101, 102, 103]
param = tuple(ids)
results = cursor.execute("select name from employee where id IN {}".format(param))
Otra opción es dar formato a una cadena con la consulta.
import cx_Oracle
ids = [101, 102, 103]
ALL_IDS = "('{0}')".format("','".join(map(str, ids)))
conn = cx_Oracle.connect('username', 'pass', 'schema')
cursor = conn.cursor()
query = """
select name from employee where id in ('{}')
""".format("','".join(map(str, ids)))
results = cursor.execute(query)
names = [x[0] for x in cursor.description]
rows = results.fetchall()
Since you created the string, you're almost there. This should work:
results = cursor.execute('select name from employee where id in ' + ALL_IDS)
I have data frame named distTest which have columns with UTF-8 format. I want to save the distTest as table in my sql database. My code is as follows;
library(RODBC)
load("distTest.RData")
Sys.setlocale("LC_CTYPE", "persian")
dbhandle <- odbcDriverConnect('driver={SQL Server};server=****;database=TestDB;
trusted_connection=true',DBMSencoding="UTF-8" )
Encoding(distTest$regsub)<-"UTF-8"
Encoding(distTest$subgroup)<-"UTF-8"
sqlSave(dbhandle,distTest,
tablename = "DistBars", verbose = T, rownames = FALSE, append = TRUE)
I considered DBMSencoding for my connection and encodings Encoding(distTest$regsub)<-"UTF-8"
Encoding(distTest$subgroup)<-"UTF-8"
for my columns. However, when I save it to sql the columns are not shown in correct format, and they are like this;
When I set fast in sqlSave function to FALSE, I got this error;
Error in sqlSave(dbhandle, Distbars, tablename = "DistBars", verbose =
T, : 22001 8152 [Microsoft][ODBC SQL Server Driver][SQL
Server]String or binary data would be truncated. 01000 3621
[Microsoft][ODBC SQL Server Driver][SQL Server]The statement has been
terminated. [RODBC] ERROR: Could not SQLExecDirect 'INSERT INTO
"DistBars" ( "regsub", "week", "S", "A", "F", "labeled_cluster",
"subgroup", "windows" ) VALUES ( 'ظâ€', 5, 4, 2, 3, 'cl1', 'Ø·Âظ…ظ„
ط²ط¨ط§ظ„ظ‡', 1 )'
I also tried NVARCHAR(MAX) for utf-8 column in the design of table with fast=false the error gone, but the same error with format.
By the way, a part of data is exported as RData in here.
I want to know why the data format is not shown correctly in sql server 2016?
UPDATE
I am fully assured that there is something wrong with RODBC package.
I tried inserting to table by
sqlQuery(channel = dbhandle,"insert into DistBars
values(N'7من',NULL,NULL,NULL,NULL,NULL,NULL,NULL)")
as a test, and the format is still wrong. Unfortunately, adding CharSet=utf8; to connection string does not either work.
I had the same issue in my code and I managed to fix it eliminating rows_at_time = 1 from my connection configuration.
I'm trying to insert data into a pre-existing PostgreSQL table using RPostgreSQL and I can't figure out the syntax for SQL parameters (prepared statements).
E.g. suppose I want to do the following
insert into mytable (a,b,c) values ($1,$2,$3)
How do I specify the parameters? dbSendQuery doesn't seem to understand if you just put the parameters in the ....
I've found dbWriteTable can be used to dump an entire table, but won't let you specify the columns (so no good for defaults etc.). And anyway, I'll need to know this for other queries once I get the data in there (so I suppose this isn't really insert specific)!
Sure I'm just missing something obvious...
I was looking for the same thing, for the same reasons, which is security.
Apparently dplyr package has the capacity that you are interested in. It's barely documented, but it's there. Scroll down to "Postgresql" in this vignette: http://cran.r-project.org/web/packages/dplyr/vignettes/databases.html
To summarize, dplyr offers functions sql() and escape(), which can be combined to produce a parametrized query. SQL() function from DBI package seems to work in exactly same way.
> sql(paste0('SELECT * FROM blaah WHERE id = ', escape('random "\'stuff')))
<SQL> SELECT * FROM blaah WHERE id = 'random "''stuff'
It returns an object of classes "sql" and "character", so you can either pass it on to tbl() or possibly dbSendQuery() as well.
The escape() function correctly handles vectors as well, which I find most useful:
> sql(paste0('SELECT * FROM blaah WHERE id in ', escape(1:5)))
<SQL> SELECT * FROM blaah WHERE id in (1, 2, 3, 4, 5)
Same naturally works with variables as well:
> tmp <- c("asd", 2, date())
> sql(paste0('SELECT * FROM blaah WHERE id in ', escape(tmp)))
<SQL> SELECT * FROM blaah WHERE id in ('asd', '2', 'Tue Nov 18 15:19:08 2014')
I feel much safer now putting together queries.
As of the latest RPostgreSQL it should work:
db_connection <- dbConnect(dbDriver("PostgreSQL"), dbname = database_name,
host = "localhost", port = database_port, password=database_user_password,
user = database_user)
qry = "insert into mytable (a,b,c) values ($1,$2,$3)"
dbSendQuery(db_connection, qry, c(1, "some string", "some string with | ' "))
Here's a version using the DBI and RPostgres packages, and inserting multiple rows at once, since all these years later it's still very difficult to figure out from the documentation.
x <- data.frame(
a = c(1:10),
b = letters[1:10],
c = letters[11:20]
)
# insert your own connection info
con <- DBI::dbConnect(
RPostgres::Postgres(),
dbname = '',
host = '',
port = 5432,
user = '',
password = ''
)
RPostgres::dbSendQuery(
con,
"INSERT INTO mytable (a,b,c) VALUES ($1,$2,$3);",
list(
x$a,
x$b,
x$c
)
)
The help for dbBind() in the DBI package is the only place that explains how to format parameters:
The placeholder format is currently not specified by DBI; in the
future, a uniform placeholder syntax may be supported. Consult the
backend documentation for the supported formats.... Known examples are:
? (positional matching in order of appearance) in RMySQL and RSQLite
$1 (positional matching by index) in RPostgres and RSQLite
:name and $name (named matching) in RSQLite
? is also the placeholder for R package RJDBC.