Composite Foreign and Primary Keys - python

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) "
"); ")

Related

How to add an action to a mysql, python written database

So I'm trying to make a project for school where a database stores the check_in and check_out time form an RFID card using a RFID reader.
create table attendance_check(
id INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
date_id DATE NOT NULL DEFAULT CURRENT_DATE,
user_id INT UNSIGNED NOT NULL,
name VARCHAR(255) NOT NULL,
clock_id TIME NOT NULL DEFAULT CURRENT_TIME,
Action VARCHAR(255) NOT NULL,
PRIMARY KEY ( id )
);
The database looks like this and for "Action" I want to add "in" and "out". I manage to add the "in" but can't figure out how to make a look-up and add an "out".
This is the code so far. I've tried 10 different variations already, I also have a database that stores the Users.
while True:
lcd.clear()
lcd.message('Place Card to\nrecord attendance')
id, text = reader.read()
cursor.execute("Select id, name FROM users WHERE rfid_uid="+str(id))
result = cursor.fetchone()
lcd.clear()
name = result[1]
number = result [0]
action1 = "in"
action2 = "out"
if cursor.rowcount >= 1:
lcd.message("Welcome " + name)
add = ("INSERT INTO attendance_check (user_id, name, Action) VALUES (%s, %s, %s)")
date = (numar, nume, action1)
cursor.execute(add, date)
db.commit()
else:
lcd.message("User does not exist.")
time.sleep(2)
I've tried to use if statements inside that checks if an action is there and if it's "in" it should add "out" but it never worked
It looks like this so far

i am trying to create multiple tables in a database [duplicate]

This question already has an answer here:
Unfindable SQLite Syntax Error
(1 answer)
Closed 9 months ago.
error: cursor.execute(
sqlite3.OperationalError: near "Order": syntax error
import sqlite3
conn = sqlite3.connect("Cookie.DB")
print("The Employee database is created!")
cursor = conn.cursor()
cursor.execute(
"""
CREATE TABLE IF NOT EXISTS Customer(
customerID TXT PRIMARY KEY NOT NULL,
customerFirstName TEXT NOT NULL,
customerLastName TXT NOT NULL,
address TXT NOT NULL,
email TXT NOT NULL,
Phone TXT NOT NULL,
creditCardInfo TXT NOT NULL
)
CREATE TABLE IF NOT EXISTS Order(
orderID TXT PRIMARY KEY NOT NULL,
FOREIGN KEY (customerID)
REFERENCES Customer (customerID),
customerName TXT NOT NULL,
FOREIGN KEY (cartID)
REFERENCES ShoppingCart (cartID),
orderPrice float NOT NULL,
dateCreated date NOT NULL,
dateShipped date NOT NULL
)
CREATE TABLE IF NOT EXISTS Cookies(
CookieID TXT PRIMARY KEY NOT NULL,
cookieName TXT NOT NULL,
unitCost float NOT NULL,
soldOutOrNot bool NOT NULL
)
CREATE TABLE IF NOT EXISTS ShoppingCart(
CartID TXT PRIMARY KEY NOT NULL,
FOREIGN KEY (customerID)
REFERENCES Customer (customerID),
FOREIGN KEY (cookieID)
REFERENCES Cookies (cookieID),
quantity INT NOT NULL,
dateAdded date NOT NULL,
soldOutOrNot bool NOT NULL
)
"""
)
conn.commit()
print("The employee table is created!")
I see the syntax you are using is wrong as far as I am able to understand try running individual queries like
import sqlite3
conn = sqlite3.connect("mydatabase.db")
cursor = conn.cursor()
# run for each table...
cursor.execute("""CREATE TABLE albums
(title text, artist text, release_date text,
publisher text, media_type text)""")

incorrect integer value mySQL

Im receiving an error where I am using an incorrect integer value for userID_fk and target. The error comes up for values which have an integer as their data type and if its changed to text or varchar it will state a site has been created and the siteID will increase but no other data will be included. I want the user to input their username so its matched with its userID and inserted into userID_fk through python with Tkinter.
Below is the structure for my users and sites table
users:
CREATE TABLE `users` (
`userID` int(255) NOT NULL AUTO_INCREMENT,
`userName` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL,
`userPassword` varchar(225) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL,
`Name` varchar(255) NOT NULL,
`phoneNum` text NOT NULL,
`email` varchar(230) NOT NULL,
`region` text NOT NULL,
`accessLevel` int(10) NOT NULL,
PRIMARY KEY (`userID`)
) ENGINE=InnoDB AUTO_INCREMENT=10002 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT
sites:
CREATE TABLE `sites` (
`siteID` int(225) NOT NULL AUTO_INCREMENT,
`siteName` text CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL,
`userID_fk` int(255) NOT NULL,
`region` text NOT NULL,
`risklevel` text NOT NULL,
`siteType` text NOT NULL,
`target` int(225) NOT NULL,
PRIMARY KEY (`siteID`),
KEY `userID_fk` (`userID_fk`),
CONSTRAINT `sites_ibfk_1` FOREIGN KEY (`userID_fk`) REFERENCES `users` (`userID`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT
Python code to insert a site into the sites table:
def register_site():
sitename_info = sitename2.get()
username2_info = username2.get()
region_info = region.get()
risklevel_info = risklevel.get()
sitetype_info = sitetype.get()
targetpercent_info = targetpercent.get()
# Sql code for writing the data that was written in the regsitering page.
cursor = cnn.cursor()
sitequery = "INSERT INTO `sites`(`siteID`, `siteName`, `userID_fk`, `region`, `risklevel`, `siteType`, `target`) VALUES (NULL,%s,%s,%s,%s,%s,%s)"
sitequery_vals = (sitename_info, username2_info, region_info, risklevel_info, sitetype_info, targetpercent_info)
cursor.execute(sitequery, sitequery_vals)
cnn.commit()
cursor.close()
cnn.close()
# removes the values in the entrys once the user selects that the registration was successful
sitename2_entry.delete(0, END)
region_entry.delete(0, END)
risklevel_entry.delete(0, END)
sitetype_entry.delete(0, END)
targetpercent_entry.delete(0, END)
Label(screen10, text = "Site Created", fg = "green", font = ("calibri", 11)).pack()
If username2_info is the userName, you need to get the userID from the users table:
sitequery = ("INSERT INTO `sites` (`siteName`, `userID_fk`, `region`, `risklevel`, `siteType`, `target`) "
"SELECT %s, `userID`, %s, %s, %s, %s FROM `users` WHERE `userName` = %s")
sitequery_vals = (sitename_info, region_info, risklevel_info, sitetype_info, targetpercent_info, username2_info)
cursor.execute(sitequery, sitequery_vals)
cnn.commit()

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))) """)

psycopg2 set PRIMARY KEY from tuple with placeholder

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')
+ ")")

Categories