I have a table name globalData, in my sqlite database, with column 'index', 'rank_d30'. While executing this query with python, i receive syntax error near ON ...
cur.execute('INSERT INTO globalData (`index`, rank_d30) VALUES(0, 9) ON CONFLICT(`index`) DO UPDATE SET rank_d30 = VALUES(rank_d30)')
How it can be corrected?
SQLite does not recognize the VALUES() syntax in the DO UPDATE clause of the query, as MySQL does in the INSERT ... ON DUPLICATE KEY syntax. To refer to the value that was initially given for insert, you must use pseudo-table excluded instead.
Consider:
INSERT INTO globalData (`index`, rank_d30)
VALUES(0, 9)
ON CONFLICT(`index`) DO UPDATE SET rank_d30 = EXCLUDED.rank_d30
Note that, for this to work, you need a unique or primary key constraint on column index.
Related
This question already has answers here:
Prevent SQLAlchemy from automatically setting IDENTITY_INSERT
(4 answers)
Closed last year.
Have this Python Flask SQLAlchemy app that fetch data from a third party SQL Server database.
There is a table with to columns that I need to insert rows:
TABLE [dbo].[TableName](
[Id] [bigint] NOT NULL,
[Desc] [varchar](150) NOT NULL,
CONSTRAINT [PK_Id] PRIMARY KEY CLUSTERED ...
The primary key is not set as IDENTITY
Using SQLAlchemy ORM, if I try to add a new row without an explicit value for Id field, I have this error:
sqlalchemy.exc.IntegrityError: (pyodbc.IntegrityError) ('23000', "[23000] ...
The column not allow Null values* (translated text)
If I explicit an Id value, another error occurs:
sqlalchemy.exc.ProgrammingError: (pyodbc.ProgrammingError) ('42000', '[42000] ...*
It is not possible to find the object "dbo.TableName", because it not exists or you don't have permissions (translated text)
This error is followed by the sentence:
[SQL: SET IDENTITY_INSERT dbo.[TableName] ON]
I'm supposing SQLAlchemy is trying to execute this command, but as Id is not set as IDENTITY, there's no need for that.
Using SQL Server Management Studio, with the same user of pyodbc connection, I'm able to insert new records, choosing whatever value for Id.
I would appreciate any hint.
Your INSERT will fail because a value must be defined for the primary key column of a table, either explicitly in your INSERT or implicitly by way of an IDENTITY property.
This requirement is due to the nature of primary keys and cannot be subverted. Further, you are unable to insert a NULL because the table definition explicitly disallows NULLs in that column.
You must provide a value in your INSERT statement explicitly due to the combination of design factors present.
Based on the documentation (https://docs-sqlalchemy.readthedocs.io/ko/latest/dialects/mssql.html#:~:text=The%20SQLAlchemy%20dialect%20will%20detect%20when%20an%20INSERT,OFF%20subsequent%20to%20the%20execution.%20Given%20this%20example%3A), it appears that SqlAlchemy may be assuming that column is an IDENTITY and is attempting to toggle IDENTITY_INSERT to on. As it is not an identity column, it is encountering an exception.
In your table metadata, check that you have autoincrement=False set for the Id column.
Edit to add: According to comments in an answer on a related question (Prevent SQLAlchemy from automatically setting IDENTITY_INSERT), it appears that SqlAlchemy assumes all integer-valued primary keys to be identity, auto-incrementing as well - meaning that you need to explicitly override that assumption as described here.
I currently am using SQL Alchemy Core specifically with the SQL Expression Language.
I have a table that is currently using the GENERATED ALWAYS AS IDENTITY parameter.
CREATE TABLE mytable(id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
col1 VARCHAR(100),col2 VARCHAR(100));
Everytime I try insert in the table, i'm getting the error:
DETAIL: Column "id" is an identity column defined as GENERATED ALWAYS.
HINT: Use OVERRIDING SYSTEM VALUE to override.
I know that if I just to use postgres I could:
INSERT INTO mytable (id,col1,col2) OVERRIDING SYSTEM VALUE
VALUES (%s,%s,%s) ON CONFLICT (id) DO NOTHING;
But how would do this using the sql expression language that sqlalchemy provides?
I am currently upserting like this:
insert_stmt = postgresql.insert(target).values(vals)
primary_keys = [key.name for key in inspect(target).primary_key]
stmt = insert_stmt.on_conflict_do_nothing(index_elements=primary_keys)
conn.execute(stmt)
I wanted OVERRIDING SYSTEM VALUE to use fixed IDs in my tests.
As far as I can see, SQLAlchemy doesn't support this at the moment.
I hacked it in this way:
#compiles(Insert)
def set_inserts_overriding_system_value(the_insert, compiler, **kw):
text = compiler.visit_insert(the_insert, **kw)
text = text.replace(") VALUES (", ") OVERRIDING SYSTEM VALUE VALUES (")
return text
You can probably create some weird tables or insert queries on purpose, that will be messed up by this text replace. But it won't ever happen by accident.
I have seen some posts that suggesting using a ? as a place holder when inserting python variables into a SQL Query but all of these examples show the question mark at the end of the query followed by the python variable. What if you want to insert a python variable in the middle of a query and want to avoid SQL injection? I am using Python 3.6 and SQLite.
Update* - This code is working:
id='13'
text='YES'
db=sqlite3.connect('NEW_Inventory.sqlite')
cursor=db.cursor()
query=('''
INSERT
OR REPLACE
INTO
text (id, text)
VALUES
(?,
(SELECT
CASE
WHEN exists(SELECT 1 FROM text WHERE id=?)
THEN 'good'
ELSE 'Hello'
END
)
)''')
cursor.execute(query, (id, id))
db.commit()
You need to pass the parameters to execute() as a tuple. In your case you need to call it like this:
cursor.execute(query, (id, id))
where query is your parameterised SQL query string.
I assume that your code defines id somewhere, otherwise, execute() will try to use the builtin function id() to construct the query, resulting in another error.
It also worth mentioning that if you have only one parameter it must also be passed as a tuple like this (id,). Avoid the common mistake of this: (id) which is not a tuple.
So I'm working in a Python 3.5.2 venv with SQLAlchemy and MySQL. I'm trying to update the status of an order (row) in a table. This requires simply changing the value of one column in a row. The following shows the function I'm working with:
def update_order_status(self, order):
newstatus = self.orderwindow.status.currentIndex()
orderid = order.orderid
stmt = update(Order)\
.where(Order.orderid == orderid).values(status=newstatus)
session.execute(stmt)
session.commit()
newstatus is an integer value taken from the current choice set
in a dropdown menu presented to the user. Upon the session.commit()the following errors are
.....
File "C:\Python35\Python35-32\lib\site-packages\MySQLdb\connections.py", line 292, in query
_mysql.connection.query(self, query)
sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (1366, "Incorrect integer value: 'Patient' for column 'bill' at row 1") [SQL: 'UPDATE `order` SET bill=%s, ship=%s, status=%s, flavor=%s WHERE `order`.orderid = %s'] [parameters: ('Patient', 'Pickup', 'Received', 7, 100000)]
......
Process finished with exit code 1
The parameters executed are not at all what is shown in the prepared statement. It should only be updating the row with the orderid matching the one provided as a parameter to the function and the status from the dropdown.
I've updated all packages and tried other methods of updating including setattr(order, "status", newstatus)
I'm unsure of what to do to diagnose this error.
EDIT: I forgot to mention earlier that this function actually works flawlessly in a python console after copy-pasting my database declarations script first.
Seems I've answered my own question. I remembered that I was querying the order table earlier in my program and then changing its attributes from integers to user-friendly strings. When the update was being called, it was using the now changed order object which had values contradicting the table column types.
I didn't know that the update function attempts to update the entire object rather than just the columns provided in the .values() field. As a result I've had to revamp my handling of orders and instead I'm putting them into dictionaries and referencing the table again to update the original order.
I am trying to alter a database but I am not sure of the exact syntax and I am having trouble finding it online. The line that is giving the error is:
cur.execute("ALTER TABLE Units ADD FOREIGN KEY(pnid), REFERENCES Basic(pnid)) ")
The error is
ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' REFERENCES Basic(pnid))' at line 1")
Remove the comma , before REFERENCES as seen below
ALTER TABLE Units ADD FOREIGN KEY(pnid), REFERENCES Basic(pnid)
<--Here
ALTER statement should look like
ALTER TABLE Units ADD FOREIGN KEY(pnid) REFERENCES Basic(pnid)
You are not using correct syntax for adding a foreign key as docs says
ALTER TABLE tbl_name
ADD [CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
You have an extra comma before REFERENCES remove it
ALTER TABLE Units ADD FOREIGN KEY(pnid) REFERENCES Basic(pnid));
Using FOREIGN KEY Constraints