psycopg2 set PRIMARY KEY from tuple with placeholder - python

How can I set a primary key in psycopg2 from a tuple of values being looped in from a tuple?
for example i have my tuple
meetattrs = ('id', 'venue', 'date', 'rail', 'weather', 'trackcondition')
and then I want to create the table and extract and insert values. From the meetattrs I wish to set id as the primary key.
conn = psycopg2.connect("")
with conn, conn.cursor() as cur:
# First, create tables.
cur.execute("drop table if exists meetings, races, horses")
cur.execute("create table meetings (id integer PRIMARY KEY, " +
", ".join("%s varchar" % fld for fld in meetattrs)
+ ")")
This however creates this error, unsure how to resolve.
Traceback (most recent call last):
File "racemeeting.py", line 56, in <module>
+ ")")
psycopg2.ProgrammingError: column "id" specified more than once

Your current sql query after the join is performed and the placeholders take their values is:
'create table meetings (id integer PRIMARY KEY, id varchar, venue varchar, date varchar, rail varchar, weather varchar, trackcondition varchar)'
id is specified twice.
You can build your query in a much cleaner way:
query_params = " %s integer PRIMARY KEY" + ", %s varchar" * (len(meetattrs) - 1)
And your SQL statement becomes:
"create table meetings (" + query_params % meetattrs + ")"
After the insertion of placeholder values:
'create table meetings (id integer PRIMARY KEY, venue varchar, date varchar, rail varchar, weather varchar, trackcondition varchar)'
Be sure your tuple always has its first item as id

In that kind of problem, you should first try to build and control the sql string.
("create table meetings (id integer PRIMARY KEY, " +
", ".join("%s varchar" % fld for fld in meetattrs)
+ ")")
gives:
'create table meetings (id integer PRIMARY KEY, id varchar, venue varchar, date varchar, rail varchar, weather varchar, trackconditionvarchar)'
effectively duplicating id column.
The solution is then trivial: remove first identifier from meetattrs:
cur.execute("create table meetings (id integer PRIMARY KEY, " +
", ".join("%s varchar" % fld for fld in meetattrs[1:])
+ ")")
Alternatively if you cannot be sure that the primary key if the first element:
cur.execute("create table meetings (id integer PRIMARY KEY, " +
", ".join("%s varchar" % fld for fld in meetattrs if fld != 'id')
+ ")")

Related

How to create table dynamically in python mysql.connector?

I got an error in the 5th line in my code below at '"+uname+"'.
How can I create a table at runtime?
Here is my code :
name = en1.get()
uname = en2.get()
password = en3.get()
sql = "insert into register values ('" + name + "','" + uname + "','" + password + "')"
CreateTable = "CREATE TABLE '"+uname+"'(no INT AUTO_INCREMENT PRIMARY KEY,title VARCHAR(255),amount INT,date DATE,mode VARCHAR(255))"
try:
cur.execute(sql)
cur1.execute(CreateTable)
con.commit()
con1.commit()
messagebox.showinfo("Success", "Your data is registered successfully!")
except:
messagebox.showinfo("Error inserting", "Please change your username and try.")
In the statements with get(), if you get None as a return value then the below statements will fail
name = en1.get() #-- None
sql = "insert into register values ('" + name + "','" + uname + "','" + password + "')"
CreateTable = "CREATE TABLE '"+uname+"'(no INT AUTO_INCREMENT PRIMARY KEY,title VARCHAR(255),amount INT,date DATE,mode VARCHAR(255))"
Try this instead so that if any of the values is None, then below output will be obtained
without causing the error but still the sql query needs to be handled
sql = "insert into register values ('{}','{}','{}')".format(name, uname, password)
CreateTable = "CREATE TABLE '{}'(no INT AUTO_INCREMENT PRIMARY KEY,title VARCHAR(255),amount INT,date DATE,mode VARCHAR(255))".format(name)
print("sql is ", sql)
print("sql is ", CreateTable)
# Output
sql is insert into register values ('None','None','None')
sql is CREATE TABLE 'None'(no INT AUTO_INCREMENT PRIMARY KEY,title VAR
CHAR(255),amount INT,date DATE,mode VARCHAR(255))

create a table with variable name (sqlite3)

i want to create a table in sqlite3 with python put when i change number1 the name of table to the name of variable make the name of variable the name of table not the value in variable
db.execute("create table if not exists number1 (ID integer primary key autoincrement, item text, quantity integer,price_per_once integer, total integer)")
Thanks in advance
Concatenate a variable:
db.execute("create table if not exists " + table_name + " (ID integer primary key autoincrement, item text, quantity integer,price_per_once integer, total integer)")
Although if you're creating lots of tables with the same stucture, there's probably a better way to design your schema. Whatever the difference is between all these tables, it should probably just be a column in the table.
Have you tried something like this:
db.execute("create table " + tableNameVariable + " (...)")

Python-MSSQL (pymssql) Set a field Identity Column

I have been trying to set the ObjectID as Identity column using python on SQL. The below SQL statment works on Management Studio (SSMS) and sets the ObjectID as Identity column. The code works, but when checking the table on SSMS, I don't see ObjectID as Identity column.
The following ways work on python but do not change the identity column on SSMS.
Adding conn.commit() after each execution.
Running the .sql file with python file reader.
Shown in the image, the Identity column is still empty after code execution in python.
The code was generated by SSMS, and my purpose is to SET ObjectID field Identity column. Maybe there is a better way.
Here is the code:
newTableName = "A_Test_DashAutomation"
try:
cursor.execute("""
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION """)
cursor.execute("""
CREATE TABLE dbo.Tmp_""" + newTableName + """
(
SubProjectTempId bigint NULL,
CIPNumber varchar(16) NOT NULL,
Label nvarchar(50) NULL,
Date_Started datetime2(7) NULL,
Date_Completed datetime2(7) NULL,
Status nvarchar(25) NULL,
Shape geography NULL,
Type varchar(2) NOT NULL,
ProjectCode varchar(16) NULL,
ActiveFlag int NULL,
Category varchar(32) NULL,
ProjectDescription varchar(64) NULL,
UserDefined varchar(1024) NULL,
InactiveReasonDate datetime NULL,
FYTDBudget money NULL,
LTDBudget money NULL,
PeriodExpenses money NULL,
FYTDExpenses money NULL,
LTDExpenses money NULL,
LTDEncumbrances money NULL,
LTDBalance money NULL,
FiscalYear int NULL,
ToPeriod int NULL,
_LastImported datetime NOT NULL,
OBJECTID int NOT NULL IDENTITY (1, 1),
GDB_GEOMATTR_DATA varbinary(MAX) NULL
) ON [PRIMARY]
TEXTIMAGE_ON [PRIMARY]
""")
cursor.execute("ALTER TABLE dbo.Tmp_" + newTableName + " SET (LOCK_ESCALATION = TABLE)")
cursor.execute("SET IDENTITY_INSERT dbo.Tmp_" + newTableName + " ON")
cursor.execute("""
IF EXISTS(SELECT * FROM dbo.""" + newTableName + """)
EXEC('INSERT INTO dbo.Tmp_""" + newTableName + """ (SubProjectTempId, CIPNumber, Label, Date_Started, Date_Completed, Status, Shape, Type, ProjectCode, ActiveFlag, Category, ProjectDescription, UserDefined, InactiveReasonDate, FYTDBudget, LTDBudget, PeriodExpenses, FYTDExpenses, LTDExpenses, LTDEncumbrances, LTDBalance, FiscalYear, ToPeriod, _LastImported, OBJECTID, GDB_GEOMATTR_DATA)
SELECT SubProjectTempId, CIPNumber, Label, Date_Started, Date_Completed, Status, Shape, Type, ProjectCode, ActiveFlag, Category, ProjectDescription, UserDefined, InactiveReasonDate, FYTDBudget, LTDBudget, PeriodExpenses, FYTDExpenses, LTDExpenses, LTDEncumbrances, LTDBalance, FiscalYear, ToPeriod, _LastImported, OBJECTID, GDB_GEOMATTR_DATA FROM dbo.""" + newTableName + """ WITH (HOLDLOCK TABLOCKX)')
""")
cursor.execute("SET IDENTITY_INSERT dbo.Tmp_" + newTableName + " OFF")
cursor.execute("DROP TABLE dbo." + newTableName)
cursor.execute("EXECUTE sp_rename N'dbo.Tmp_" + newTableName + "', N'" + newTableName + "', 'OBJECT'")
cursor.execute("""
ALTER TABLE dbo.""" + newTableName + """ ADD CONSTRAINT
R1143_pk PRIMARY KEY CLUSTERED
(
OBJECTID
) WITH( PAD_INDEX = OFF, FILLFACTOR = 75, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
""")
cursor.execute("""
CREATE SPATIAL INDEX SIndx ON dbo.""" + newTableName + """(Shape) USING GEOGRAPHY_AUTO_GRID
WITH( CELLS_PER_OBJECT = 16, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
""")
cursor.execute("""
ALTER TABLE dbo.""" + newTableName + """ ADD CONSTRAINT
g1084_ck CHECK (([Shape].[STSrid]=(4326)))
""")
cursor.execute("COMMIT")
conn.commit()
print("Object ID is set to Identify column.")
except pymssql.DatabaseError, err:
print(str(err))
Any help would be appreciated.
Thanks
Problem solved. The STSrid changes everytime you create a new table, so taking this portion out of the SQL code helped. However, I am not sure if the spatial index remained the same.
Cheers
cursor.execute("""
ALTER TABLE dbo.""" + newTableName + """ ADD CONSTRAINT
g1084_ck CHECK (([Shape].[STSrid]=(4326))) """)

Composite Foreign and Primary Keys

I want to create two tables one that contains unique values of City and Country and one that contains values of City, Country, timestamp and VisitedDays. City and Country will be a composite primary key in table 1.
I have a problem with the below script which is that I cannot input a new row with city and country values that have been previously added to table 2. In other words, I cannot input data from a second trip to the same city and country in table 2. Is there a way to have a composite primary key and have multiple rows with the same foreign key values. Based on the error my problem is related with the UNIQUE declaration of the ID.
Error:
psycopg2.IntegrityError: duplicate key value violates unique constraint "trips_pkey"
DETAIL: key (city, country) = (San Juan, Puerto Rico) already exists.
Note: I reduced most of my script for this question. In the original script the TABLE 1 (primaryIds) is populated only when there is a distint (City,Country) and table 2 is populated with every log (trip). Also I didn't include the Insert portion of the script for the table 2 because it works for all entry except with the same (City,Country).
import sys, psycopg2
with psycopg2.connect("dbname='XXXXX' user='YYYYY' password='ZZZZ'") as outdb:
cur. outdb.cursor()
cur.execute("CREATE TABLE primaryIds "
"( "
"City VARCHAR(20) NOT NULL, "
"Country VARCHAR(20) NOT NULL, "
"PRIMARY KEY (City, Country), "
"UNIQUE (City) "
"); ")
cur.execute("INSERT INTO primaryIds "
"(City, Country)"
" VALUES "
"(%s, %s)", (a, b))
cur.execute("CREATE TABLE trips "
"( "
"City VARCHAR(20) NOT NULL, "
"Country VARCHAR(20) NOT NULL, "
"Timestamp TIMESTAMP, "
"visitedDays INT, "
"Ids VARCHAR(20) REFERENCES primaryIds(City), "
"PRIMARY KEY (City, Country) "
"); ")
You have set trips to have a composite primary key of City and Country - it should be City, Countr, Timestamp (if it lets you) or you could create a new field automatically called tripID which is the primary key and unique. I would favor a tripID.
This is the solution for my problem.
import sys, psycopg2
with psycopg2.connect("dbname='XXXXX' user='YYYYY' password='ZZZZ'") as outdb:
cur. outdb.cursor()
cur.execute("CREATE TABLE primaryIds "
"( "
"City VARCHAR(20) NOT NULL, "
"Country VARCHAR(20) NOT NULL, "
"PRIMARY KEY (City, Country) "
"); ")
cur.execute("INSERT INTO primaryIds "
"(City, Country)"
" VALUES "
"(%s, %s)", (a, b))
cur.execute("CREATE TABLE trips "
"( "
"City VARCHAR(20) NOT NULL, "
"Country VARCHAR(20) NOT NULL, "
"Timestamp TIMESTAMP, "
"visitedDays INT, "
"FOREIGN KEY (City, Country) REFERENCES primaryIds(City,Country) "
"); ")

(python) Databases, incorrect syntax error

I'm completely new to databases, and have put something simple together using the helpful guide that can be located at http://halfcooked.com/presentations/osdc2006/python_databases.html , However it's returning an error that I don't understand
try:
from sqlite3 import dbapi2 as sqlite
except ImportError:
from pysqlite2 import dbapi2 as sqlite
db_connection = sqlite.connect('program.db')
db_curs = db_connection.cursor()
def create_customer(cID, fname, sname, dob):
db_curs.execute("CREATE TABLE " + cID + " ( id INTEGER PRIMARY KEY, first_name VARCHAR(20),last_name VARCHAR(30), date_of_birth DATE)")
db_curs.execute("INSERT INTO " + cID + " (first_name, last_name, date_of_birth) VALUES (fname, sname, dob)")
db_connection.commit()
db_curs.execute("SELECT * FROM " + cID )
create_customer("1", "John", "Farnham", "12/08/95")
create_customer("1", "Indianna", "Jones", "05/05/95")
print db_curs.fetchall()
the error I am receiving is as follows:
Traceback (most recent call last):
File "C:\Users\fin0005\Documents\loyalty.py", line 17, in <module>
create_customer("1", "John", "Farnham", "12/08/95")
File "C:\Users\fin0005\Documents\loyalty.py", line 12, in create_customer
db_curs.execute("CREATE TABLE " + cID + " ( id INTEGER PRIMARY KEY, first_name VARCHAR(20),last_name VARCHAR(30), date_of_birth DATE)")
OperationalError: near "1": syntax error
Add backticks around your table name, so that it doesn't think it's creating an integer as a table name
def create_customer(cID, fname, sname, dob):
db_curs.execute("CREATE TABLE `" + cID + "` ( id INTEGER PRIMARY KEY, first_name VARCHAR(20),last_name VARCHAR(30), date_of_birth DATE)")
db_curs.execute("INSERT INTO `" + cID + "` (first_name, last_name, date_of_birth) VALUES (fname, sname, dob)")
db_connection.commit()
db_curs.execute("SELECT * FROM `" + cID + "`")
# In SQL terms, the following blows up
# create table 2 (id int(10) PRIMARY KEY); Due to the 2 being an integer
# create table `2` (id int(10) PRIMARY KEY); Works, due to the 2 being properly identified with backticks :)
# Here's some code as requested in the comment, everything below this point is a self contained example, please do not copy the function above
def initiate_customer_table(table_name):
db_curs.execute("CREATE TABLE IF NOT EXISTS `" + table_name + "` ( id INTEGER PRIMARY KEY, first_name VARCHAR(20),last_name VARCHAR(30), date_of_birth DATE)")
db_connection.commit()
def create_customer(table_name, fname, sname, dob):
db_curs.execute("INSERT INTO `" + table_name + "` (first_name, last_name, date_of_birth) VALUES (%s, %s, %s)", [fname, sname, dob])
db_connection.commit()
# Fetches the user just created
db_curs.execute("SELECT * FROM `" + table_name + "` WHERE id = %s", [db_curs.insert_id()])
# Returns the user
return db_curs.fetchone()
desired_table_name = 'customers'
initiate_customer_table(desired_table_name)
customer_1 = create_customer(desired_table_name, "Bryan", "Moyles", "1800-01-01")
customer_2 = create_customer(desired_table_name, "Awesome", "Guy", "1800-01-01")
I will also suggest that you go a step further, if you plan on using this code in production, to ensure that all fields are escaped properly for mysql.

Categories