PostgreSQL: Unable to drop a specific table named "user" - python

I'm unable to delete a specific table in my PostgreSQL database. That table is called "user". When I try to run the snippet of code below,
import psycopg2
conn = psycopg2.connect("dbname='mydatabase' user='postgres' host='localhost' password='mypassword'")
cur = conn.cursor()
cur.execute("DROP TABLE user;")
conn.commit()
conn.close()
It spits out the following error
Traceback (most recent call last):
File "dev_psycog.py", line 20, in <module>
cur.execute("DROP TABLE user;")
psycopg2.ProgrammingError: syntax error at or near "user"
LINE 1: DROP TABLE user;
I can delete any other table in my database just fine, but I can't seem to delete my table called "user". Is it because "user" is a reserved keyword?

Quote "user" as below
import psycopg2
conn = psycopg2.connect("dbname='mydatabase' user='postgres' host='localhost' password='mypassword'")
cur = conn.cursor()
cur.execute('DROP TABLE "user";')
conn.commit()
conn.close()
See here.
There is a second kind of identifier: the delimited identifier or
quoted identifier. It is formed by enclosing an arbitrary sequence of
characters in double-quotes (").

Related

Copying a table from an in-memory database to a on-disk database in sqlite3

I want to copy one specific table from an in-memory sqlite database, using Python (3.9). Looking in the documentation, I should be able to simply attach the in-memory database to the file database, however while attaching throws no error, when I try to copy the table over, it results in the following error:
Traceback (most recent call last):
File "[insert python file URL here]", line 21, in
file_cursor.execute(f'CREATE TABLE "{table_name}" AS SELECT * FROM db."{table_name}";')
sqlite3.OperationalError: no such table: db.table_name
So, even though it is attaching the database just fine (or at least a memory database), it appears not to be able to find the tables within that database. What can I do?
test code:
import sqlite3
#memory database
conn = sqlite3.connect(":memory:")
cursor = conn.cursor()
#file database
file_conn= sqlite3.connect(r"C:\...\testfile.sqlite") #insert your own URL here
file_cursor = file_conn.cursor()
table_name = "table_name"
#Create table in memory db
cursor.execute(f"CREATE TABLE {table_name} (id INTEGER, Value INTEGER, Value2 INTEGER, Category INTEGER);")
conn.commit()
cursor.execute(f"INSERT INTO {table_name} (id, Value, Value2, Category) "
f"VALUES ('1', '20','20', '2'),"
f"('2', '30','30', '2'),"
f"('13', '17','17','1');")
conn.commit()
# copy table to file db
file_cursor.execute(f"ATTACH DATABASE ':memory:' AS db;")
file_conn.commit()
file_cursor.execute(f"CREATE TABLE '{table_name}' AS SELECT * FROM db.'{table_name}';")
file_conn.commit()
file_conn.close()
conn.close()
You don't need a separate connection to the file db.
Use the connection of the in-memory db to attach the file db:
import sqlite3
#connection to memory db
conn = sqlite3.connect(":memory:")
cursor = conn.cursor()
table_name = "table_name"
#Create table in memory db
cursor.execute(f"CREATE TABLE [{table_name}] (id INTEGER, Value INTEGER, Value2 INTEGER, Category INTEGER);")
cursor.execute(f"INSERT INTO [{table_name}] (id, Value, Value2, Category) "
f"VALUES ('1', '20','20', '2'),"
f"('2', '30','30', '2'),"
f"('13', '17','17','1');")
conn.commit()
# copy table to file db
cursor.execute(r"ATTACH DATABASE 'C:\...\testfile.sqlite' AS db;")
cursor.execute(f"CREATE TABLE db.[{table_name}] AS SELECT * FROM [{table_name}];")
conn.commit()
conn.close()

Insert data to SQL Server with Python (3.7.4)

I am trying to insert data to my table in Microsoft SQL Server using a Python script.
Initially I am trying to upload an excel file, but got error messages and have tried to lesser the scale of the task. At this point I am trying to push some data trough to an already existing table in my database. In this example my servername is SERVERNAME, database is DATABASENAME and my table is TABLE. The script is:
import pyodbc
conn = pyodbc.connect('Driver={SQL Server};'
'Server=SERVERNAME;'
'Database=DATABASENAME;'
'Trusted_Connection=yes;')
cursor = conn.cursor()
cursor.execute('INSERT INTO DATABASENAME.dbo.TABLE(Name, Age, City)
VALUES ('Alan', '30', 'London');
for row in cursor:
print(row)
I get this error message:
Traceback (most recent call last):
File "<pyshell#38>", line 1, in <module>
exec(open("C:\\pandasql.py").read())
File "<string>", line 9
cursor.execute('INSERT INTO DATABASENAME.dbo.TABLE (Name, Age, City)
^
SyntaxError: EOL while scanning string literal
I want the one row with data to be seen in my database. What am I doing wrong?
If you want to use single quotes within a single-quote string you need to escape them by adding a \ before them - or using a double-quote string.
Example:
import pyodbc
conn = pyodbc.connect('Driver={SQL Server};'
'Server=SERVERNAME;'
'Database=DATABASENAME;'
'Trusted_Connection=yes;')
cursor = conn.cursor()
cursor.execute("INSERT INTO DATABASENAME.dbo.TABLE(Name, Age, City) VALUES ('Alan', '30', 'London')")
If you want your changes to be saved to the database, you also need to call commit on the connection or set autocommit to True:
# either enable autocommit
conn = pyodbc.connect('...CONNECTION STRING...', autocommit=True)
# or after inserting the row:
conn.commit()
If you want to retrieve the resulting row, you need to select it first, e.g.:
cursor.execute("SELECT * FROM DATABASENAME.dbo.TABLE")
for row in cursor:
print(row)
or use an OUTPUT clause on your INSERT statement:
cursor.execute("""
INSERT INTO DATABASENAME.dbo.TABLE(Name, Age, City)
OUTPUT Inserted.Name, Inserted.Age, Inserted.City
VALUES ('Alan', '30', 'London')
""")
for row in cursor:
print(row)
Full example for your code snippet:
import pyodbc
conn = pyodbc.connect('Driver={SQL Server};'
'Server=SERVERNAME;'
'Database=DATABASENAME;'
'Trusted_Connection=yes;')
cursor = conn.cursor()
cursor.execute("""
INSERT INTO DATABASENAME.dbo.TABLE(Name, Age, City)
OUTPUT Inserted.Name, Inserted.Age, Inserted.City
VALUES ('Alan', '30', 'London')
""")
for row in cursor:
print(row)
conn.commit()
The colors in the snippet should already show you the problem: you are using a single quote to begin the string and end your string somewhere in between through using another single quote.
A simple way would be to escape that qoute (through adding a \ in front); a better way that also helps to secure your code against SQL injection would be to use prepared statements

Is commit used on the connect or cursor?

The book named "Practical Programming: 2nd Edition" has conflicting code. This is the start of my code:
import sqlite3
con = sqlite3.connect('stackoverflow.db')
cur = conn.cursor()
To commit, would I use con.commit(), cur.commit() or are there different times to use each? From the book:
con.commit() :
cur.commit() :
Documentation shows con.commit() :
I took unutbu's advice and tried it myself.
Sample code:
import sqlite3
con = sqlite3.connect('db.db')
cur = con.cursor()
data = [('data', 3), ('data2', 69)]
cur.execute('CREATE TABLE Density(Name TEXT, Number INTEGER)')
for i in data:
cur.execute('INSERT INTO Density VALUES (?, ?)', (i[0], i[1]))
cur.commit()
PyCharm Run:
Traceback (most recent call last):
File "/Users/User/Library/Preferences/PyCharmCE2018.1/scratches/scratch_2.py", line 13, in <module>
cur.commit()
AttributeError: 'sqlite3.Cursor' object has no attribute 'commit'
Error in textbook. cur.commit() does not exist.
Thanks unutbu and s3n0
con.commit() and conn.commit() are the same ... they are created object types ... in both cases they are otherwise named ... important is mainly .commit() and not the naming that the programmer has specified
There are object types that use a different name (con and cur - as you asked) to calling the method. You can also use a different name in your code, for example:
db = sqlite3.connect('/tmp/filename.db')
cursor = db.cursor()
cursor.execute("CREATE TABLE ....
.... some DB-API 2.0 commands ....
")
db.commit()
Please check again the webpage https://docs.python.org/3/library/sqlite3.html .
You forgot to copy these two lines from the webpage:
import sqlite3
conn = sqlite3.connect('example.db')
And then continuing the code (just copied it):
c = conn.cursor()
# Create table
c.execute('''CREATE TABLE stocks
(date text, trans text, symbol text, qty real, price real)''')
# Insert a row of data
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
# Save (commit) the changes
conn.commit()
# We can also close the connection if we are done with it.
# Just be sure any changes have been committed or they will be lost.
conn.close()
I think if you're using a specified cursor to commit changes, in your case, it should be cur.connection.commit().
You can always use connect to commit in the end of your code, whether it's named db, or con or conn.
But when your code gets complicated, you'll have different function to do certain operation to the database, if you only use connection commit, when there is a bug, you gonna have a hard time to find which function failed. So you create specific cursor for specific operation, when that failed, the traceback message will show you which specific cursor when wrong.
To #s3n0 & #DanielYu's point they can be handled two different ways. I had to list these out to better understand the overlap:
Connection Objects
backup
close
commit
create_aggregate
create_collation
create_function
cursor
enable_load_extension
execute
executemany
executescript
in_transaction
interrupt
isolation_level
iterdump
load_extension
rollback
row_factory
set_authorizer
set_progress_handler
set_trace_callback
text_factory
total_changes
Cursor objects
arraysize
close
connection
description
execute
executemany
executescript
fetchall
fetchmany
fetchone
lastrowid
rowcount
setinputsizes
setoutputsize

Python SQLite3: Cannot Create Table with Variable in Query

I have the following code to create a table if it does not already exist in a database.
TABLE_NAME = 'Test'
sql = sqlite3.connect('DATABASE.db')
cur = sql.cursor()
cur.execute('CREATE TABLE IF NOT EXISTS ? (id TEXT)', [TABLE_NAME])
sql.commit()
But I keep getting sqlite3.OperationalError: near "?": syntax error
I have other code such as cur.execute('INSERT * INTO database VALUES(?,?)', [var1, var2]) that works fine.
That is correct, parameters cannot be used to substitute for database identifiers, only for values. You will have to build the SQL command, with the table name specified, as a string.
The following code creates the table
import sqlite3
sql = sqlite3.connect('DATABASE.db')
cur = sql.cursor()
cur.execute('CREATE TABLE IF NOT EXISTS Test (id TEXT)')
sql.commit()

python inserting single quotes (') around MySQL table name

I have a database called project1 with the following tables:
_systbl1
_systbl2
_systbl3
dataset1
dataset2
dataset3
MySQL user odbc will need to be granted SELECT permissions on dataset% tables whenever a new one is added.
To accomplish this, I'm using a simple python script, like so:
#!/usr/bin/python
import MySQLdb
db = MySQLdb.connect(
host="localhost",
user="user",
passwd="pass",
db="project1"
)
# Create Cursor Object
cur = db.cursor()
# get list of tables beginning with dataset
cur.execute("SHOW TABLES FROM project1 LIKE 'dataset%';")
# run GRANT statement for each table
for row in cur.fetchall() :
cur.execute("GRANT SELECT ON `project1`.`%s` TO `odbc`#`localhost`;", row)
cur.execute("GRANT SELECT ON `project1`.`%s` TO `odbc`#`%`;", row)
Unfortunately, it gives me the following error:
Traceback (most recent call last):
File "mysql_query.py", line 20, in <module>
cur.execute("GRANT SELECT ON `project1`.`%s` TO `odbc`#`localhost`;", row)
File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 174, in execute
self.errorhandler(self, exc, value)
File "/usr/lib/python2.7/dist-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
_mysql_exceptions.ProgrammingError: (1146, "Table 'project1.'dataset1'' doesn't exist")
As you can see in the last line of the error, the problem is that python is putting a single quote around the table names when generating the query.
What am I missing here?
Do not use SQL parameters for table names. SQL parameters are escaped by the database adapter to not be interpreted as anything but literal values.
You'll have to interpolate those yourself instead, but be absolutely certain that your table name does not hold untrusted data (prevent SQL injection attacks):
cur.execute("GRANT SELECT ON `project1`.`%s` TO `odbc`#`localhost`;" % row)
cur.execute("GRANT SELECT ON `project1`.`%s` TO `odbc`#`%%`;" % row)
(where the % character in the grant has been escaped by doubling it to %%).
Instead use:
cur.execute("GRANT SELECT ON `project`.`%s` TO `odbc`#`localhost`" % row)
This will not use the normal escaping of the input. Beware of a backtick in any of your table names, though.
sql = """CREATE TABLE IF NOT EXISTS `""" + project + """` ( `id` INT(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`))"""

Categories

Resources