I create a table with primary key and autoincrement.
with open('RAND.xml', "rb") as f, sqlite3.connect("race.db") as connection:
c = connection.cursor()
c.execute(
"""CREATE TABLE IF NOT EXISTS race(RaceID INTEGER PRIMARY KEY AUTOINCREMENT,R_Number INT, R_KEY INT,\
R_NAME TEXT, R_AGE INT, R_DIST TEXT, R_CLASS, M_ID INT)""")
I want to then insert a tuple which of course has 1 less number than the total columns because the first is autoincrement.
sql_data = tuple(b)
c.executemany('insert into race values(?,?,?,?,?,?,?)', b)
How do I stop this error.
sqlite3.OperationalError: table race has 8 columns but 7 values were supplied
It's extremely bad practice to assume a specific ordering on the columns. Some DBA might come along and modify the table, breaking your SQL statements. Secondly, an autoincrement value will only be used if you don't specify a value for the field in your INSERT statement - if you give a value, that value will be stored in the new row.
If you amend the code to read
c.executemany('''insert into
race(R_number, R_KEY, R_NAME, R_AGE, R_DIST, R_CLASS, M_ID)
values(?,?,?,?,?,?,?)''',
sql_data)
you should find that everything works as expected.
From the SQLite documentation:
If the column-name list after table-name is omitted then the number of values inserted into each row must be the same as the number of columns in the table.
RaceID is a column in the table, so it is expected to be present when you're doing an INSERT without explicitly naming the columns. You can get the desired behavior (assign RaceID the next autoincrement value) by passing an SQLite NULL value in that column, which in Python is None:
sql_data = tuple((None,) + a for a in b)
c.executemany('insert into race values(?,?,?,?,?,?,?,?)', sql_data)
The above assumes b is a sequence of sequences of parameters for your executemany statement and attempts to prepend None to each sub-sequence. Modify as necessary for your code.
Related
rows_order = "SELECT COUNT (*) FROM 'Order'"
cursor.execute(rows_order)
ordernum = cursor.fetchall()
connection.commit()
cursor.execute("INSERT INTO 'Order' (OrderNo, CustomerID, Date, TotalCost) VALUES (?,?,?,?)", (
[ordernum], custid_Sorder, now, total_item_price))
This is what I am trying but this error popped up;
sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type.
How do I fix this? I want to make it so the OrderNo is = to the amount of orders before it, hence why I want to assign the orderno to it. (I am using sqlite3)
as you have only one value you need only fetchone
import sqlite3
con = sqlite3.connect("tutorial.db")
cursor = con.cursor()
rows_order = "SELECT COUNT (*) FROM 'Order'"
cursor.execute(rows_order)
ordernum = cursor.fetchone()[0]
cursor.execute("INSERT INTO 'Order' (OrderNo, CustomerID, Date, TotalCost) VALUES (?,?,?,?)", (
ordernum, custid_Sorder, now, total_item_price))
tl;dr Don't do this. Use an auto-incremented primary key.
fetchall returns all rows as a list, even if there is only one row.
Instead, use fetchone. This will return a single tuple which you can then select the first item. ordernum = cursor.fetchone()[0]
However, you appear to be writing a query to get the next ID. Using count(*) is wrong. If there are any gaps in OrderNo, for example if something gets deleted, it can return a duplicate. Consider [1, 3, 4]; count(*) will return 3. Use max(OrderNo) instead.
Furthermore, if you try to insert two orders at the same time you might get a race condition and one will try to duplicate the other.
process 1 process 2
select max(orderNo)
fetchone # 4
select max(orderNo)
fetchone # 4
insert into orders...
insert into orders... # duplicate OrderNo
To avoid this, you have to do both the select and insert in a transaction.
process 1 process 2
begin
select max(orderNo)...
fetchone # 4 begin
select max(orderNo)
fetchone
insert into orders... # wait
commit # wait
# 5
insert into orders...
commit
Better yet, do them as a single query.
insert into "Order" (OrderNo, CustomerID, Date, TotalCost)
select max(orderNo), ?, ?, ?
from "order"
Even better don't do it at all. There is a built-in mechanism to do this use an auto-incremented primary keys.
-- order is a keyword, pluralizing table names helps to avoid them
create table orders (
-- It is a special feature of SQLite that this will automatically be unique.
orderNo integer primary key
customerID int,
-- date is also a keyword, and vague. Use xAt.
orderedAt timestamp,
totalCost int
)
-- orderNo will automatically be set to a unique number
insert into orders (customerID, orderedAt, totalCost) values (...)
I have created a python list with 41 columns and 50 rows.
Now I want to insert this into an SQLite database.
When I execute the database export, I got the error message:
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 41, and there are 40 supplied.
Most of the list fields should have data. Perhaps one or two don't have any.
Can I write into the sqlite database with a prompt like:
insert if data available, otherwise write none
Or something like this?
My code is like:
c.execute("""CREATE TABLE IF NOT EXISTS statstable (
spielid integer PRIMARY KEY,
41x field descr. (real, integer and text)
UNIQUE (spielid)
)
""")
c.executemany("INSERT OR REPLACE INTO statstable VALUES (41x ?)", all_data)
Append the appropriate number of None values to the nested lists to make them all 41 elements:
c.executemany("INSERT OR REPLACE INTO statstable VALUES (41x ?)",
[l + [None] * (41 - len(l)) for l in all_data])
This assumes the missing elements are always at the end of the list of columns. If they can be different columns in each row, I don't see how you can implement any automatic solution.
If the elements of all_data were dictionaries whose keys correspond to column names, you could determine which keys are missing. Then turn it into a list with the None placeholders in the appropriate places for those columns.
I believe that the row must be first be created as to get a self increment PK. Then i could replace the one column with PK value generated . But i am not getting the proper result.
insert = "insert into table(name, status) values (:Name, :Status)
params = {'Name': Jack,
'status' : active
}
db.execute(insert, params)
db.commit()
insert_type = "replace into table (type) values (select id from table)"
db.execute(insert_type)
db.commit()
so the table does have columns as id(auto increment ), name, status and type(default 0 or id)
Insert primary key column value to Non Primary key column in same table.
You can use last_insert_rowid() to get the rowid of the row that was just inserted. For example your second query could be :
update mytable set type = id where id = last_insert_rowid()
This only work if the update if executed right after the insert and no other thread is modifying the db at the same time.
Another solution could be to set type to null (either as default or in the inserted values) then use coalesce(type, id) in the queries.
I think you can use DEFUALT = blank to create a defualt value for any column.
I'm making a database that takes user input and storing it in the database. However I want each row in the database (db) to be unique to each user and to contain separate input (thats the users put in)
This is the code I have so far:
user_id = random_number_genned_here
keyword = input_from_user
sqlite_file = 'keywords.sqlite'
conn = sqlite3.connect(sqlite_file)
c = conn.cursor()
c.execute("""CREATE TABLE IF NOT EXISTS keyword(userid TEXT UNIQUE, keyword TEXT)""")
try:
c.execute("""INSERT INTO keyword (userid , keyword) VALUES (?, ?, )""", (user_id,ukeyword))
except:
#where I need help
So basically what I need to do 2 things.
First thing: I need to see if a userid is already in the databse. The try and except does that. If it isn't in the database then I need to create a row in the database for that userid and add the keyword into the keyword column.
If a userid is already in the database then I need to add the keyword to the column.
Second thing: If the keyword column has some text in it, then I need to column to store the new keyword in.
I have bit and pieces of it but I don't know how to put it together.
To add a column to a table you can use the ALTER TABLE SQL
ALTER TABLE keyword ADD COLUMN your_column_definition
SQL As Understood By SQLite ALTER TABLE
You would have to generate the SQL programatically.
However, it would be simpler to look at the design of the keyword table. Why have the userid as UNIQUE when there are multiple data items to be stored per userid? I'd suggest that matters would be simplified if you were to have a composite UNIQUEness that is make userid and keyword combined as UNIQUE.
e.g. perhaps use :-
CREATE TABLE IF NOT EXISTS keyword(userid TEXT, keyword TEXT, UNIQUE(userid,keyword));
Perhaps consider the following demo :-
DROP TABLE IF EXISTS keyword;
CREATE TABLE IF NOT EXISTS keyword(userid TEXT, keyword TEXT, UNIQUE(userid,keyword));
INSERT OR IGNORE INTO keyword VALUES
('User001','TEST'),('User001','NOT A TEST'),('User001','KEYWORD A'),('User001','TEST'),
('User002','TEST'),('User002','KEYWORD A'),('User002','KEYWORD B')
;
-- Ooops (not really as duplicates just get ignored)
INSERT OR IGNORE INTO keyword VALUES
('User001','TEST'),('User001','NOT A TEST'),('User001','KEYWORD A'),('User001','TEST'),
('User002','TEST'),('User002','KEYWORD A'),('User002','KEYWORD B')
;
SELECT * FROM keyword;
SELECT * FROM keyword WHERE userid = 'User001';
When run the message log shows :-
DROP TABLE IF EXISTS keyword
> OK
> Time: 0.439s
CREATE TABLE IF NOT EXISTS keyword(userid TEXT, keyword TEXT, UNIQUE(userid,keyword))
> OK
> Time: 0.108s
INSERT OR IGNORE INTO keyword VALUES
('User001','TEST'),('User001','NOT A TEST'),('User001','KEYWORD A'),('User001','TEST'),
('User002','TEST'),('User002','KEYWORD A'),('User002','KEYWORD B')
> Affected rows: 6
> Time: 0.095s
-- Ooops (not really as duplicates just get ignored)
INSERT OR IGNORE INTO keyword VALUES
('User001','TEST'),('User001','NOT A TEST'),('User001','KEYWORD A'),('User001','TEST'),
('User002','TEST'),('User002','KEYWORD A'),('User002','KEYWORD B')
> Affected rows: 0
> Time: 0s
SELECT * FROM keyword
> OK
> Time: 0s
SELECT * FROM keyword WHERE userid = 'User001'
> OK
> Time: 0s
Note that the second insert inserts 0 rows as they are all duplicates
The queries produce :-
At the moment i do not have set INTEGER PRIMARY KEY as i do not need it but i will if it is the easiest way.
So i set up my database and table:
conn = sqlite3.connect('lista.db')
c = conn.cursor()
c.execute('CREATE TABLE IF NOT EXISTS unu(echipa1 TEXT UNIQUE, scor1 TEXT, scor2 TEXT, echipa2 TEXT, '
'cota FLOAT, miza INT, stare INT)')
i insert some values
c.execute("INSERT OR IGNORE INTO unu( echipa1,scor1, scor2, echipa2, cota, miza, stare ) VALUES (?,?,?,?,?,?,?)",
(echipa1, scor1, scor2, echipa2, cota, miza, stare))
so how do i select the value for stare from the last row?
c.execute("SELECT stare FROM unu WHERE id = Max")
So i know i do not have an id, but does sqlite count the rows even if i do not assign a id to each row?
If not i will set a INTEGER PRIMARY KEY
c.execute('CREATE TABLE IF NOT EXISTS unu(id INTEGER PRIMARY KEY, echipa1 TEXT UNIQUE, scor1 TEXT, scor2 TEXT, echipa2 TEXT, '
'cota FLOAT, miza INT, stare INT)')
Will then my select query work?
This depends on your definition of last row. If you want to select the row you just inserted, you can use cursor.lastrowid.
c.execute("SELECT stare FROM unu WHERE ROWID=(?)", (c.lastrowid,))
If you want the last row anyone inserted (someone may have inserted a row between the insert and select statements), then you need a PK with AUTOINCREMENT (just "id INTEGER PRIMARY KEY" will make it a copy of the ROWID which is not guaranteed to be in crescent order):
c.execute("SELECT stare FROM unu ORDER BY id DESC LIMIT 1")
You don't just need to declare the INTEGER PRIMARY KEY column but also make it AUTOINCREMENT to really guarantee the latest inserted row also has the largest ROWID/primary key value. Otherwise SQLite may fill ”holes” left by deleted rows or failed/rolled back transactions.