Need to execute SQL query dynamically - python-3.x

I need to update name of customer using the input provided by the user.
original_name need to be updated by new_name
cur.execute('''
CREATE TABLE customer (customerId int,customerName varchar(20),telephoneNo int,
addressId varchar(20), customerType varchar(20),
discount int, memCardType varchar(20))''')
I'm trying to perform this code, but it gives an error.
original_name=input("Enter name to be modified: ")
new_name=input("Enter new name of the customer: ")
cur.execute("UPDATE customer SET customerName=new_name WHERE customerName=original_name ")
print("Customer name changes successfully.")
Error:
cur.execute("UPDATE customer SET customerName=new_name WHERE
customerName=original_name ")
cx_Oracle.DatabaseError: ORA-00904: "ORIGINAL_NAME": invalid identifier

I suppose you use a SQL cursor so I would do it like that :
original_name=input("Enter name to be modified: ")
new_name=input("Enter new name of the customer: ")
cur.execute("UPDATE customer SET customerName=:new_name WHERE customerName=:cust_name",{'cust_name': original_name, 'new_name' : new_name})
print("Customer name changes successfully.")
The concept is simple. :new_name and :cust_name are binding parameters, in fact you told to your function you will add this parameter as variable then in
{'cust_name': original_name, 'new_name' : new_name}
You just fill those binding parameters with your variables.

Related

one2many field stores only last record when fill

please help me regarding one2many field in odoo12.
firstly, sorry for bad grammar.
i am getting products from invoice_line_ids of account.invoice model.
but when i store these products in my custom model only last record is stored in one2many field in my class.
here is my code.
invoice_report = self.create(vals)
product_dict={}
product_list=[]
for line in ids.invoice_line_ids:
product_dict.update({
'product_name':line.product_id.name,
'qty':line.quantity,
'unit_price':line.price_unit,
'tax':line.invoice_line_tax_ids.name or "",
'subtotal':line.price_subtotal
})
product_list.append([(1,invoice_report.id,product_dict)])
for data in product_list:
invoice_report.write({
'inv_products':data
})
inv_products is my one2many field
invoice_report is my recently created record. i.e custom.invoice(1,)
According to the x2many values filling, the format you used updates an existing record of id id with the values in values. id should be an id of an inv_products record, not a custom.invoice record.
You should receive an Odoo server error in case record with id equal to 1 does not exist in the database:
One of the records you are trying to modify has already been deleted (Document type: custom.report.line).
(Records: (1,), User: 2)
You declared product_dict outside a for loop and you used update inside, at the end of the loop you will have the values of the last line of invoice_line_ids repeated, You asked the system to update a specific line (with id invoice_report.id) with the same values in each iteration when you called write method.
To add new records to inv_products, use [(0, 0, values)] format:
invoice_report = self.create(vals)
product_list = []
for line in ids.invoice_line_ids:
product_dict = {
}
product_list.append((0, 0, product_dict))
invoice_report.write({
'inv_products': product_list
})

UPSERT syntax error linked to UPDATE in PostgreSQL (python)

I'm still learning PostgreSQL. During my testing, I have only been using INSERT statement in either psycopg2 and now asyncpg. I now have the need to UPDATE data in my test database, instead of replacing all of it.
I'm currently trying to do a simple replacement test in a testing table, before I move to development table with more data.
I want to replace any $1 name that is in CONFLICT with a name that is already in the table users. I'm trying the query code, which is passed to the DB via asyncpg. I keep getting a syntax errors, so I'm a little lost on how to correct these errors.
What is the proper syntax for this query?
'''INSERT INTO users(name, dob)
VALUES($1, $2)
ON CONFLICT (name)
DO
UPDATE "users"
SET name = 'TEST'
WHERE name = excluded.name '''
UPDATE:
I'm getting this error message when using asyncpg:
asyncpg.exceptions.PostgresSyntaxError: syntax error at or near ""users""
I'm getting this error message when using psycopg2:
psycopg2.ProgrammingError: syntax error at or near ""users""
This is the asyncpg code that I have been using to do the INSERTs:
async def insert_new_records(self, sql_command, data):
print (sql_command)
async with asyncpg.create_pool(**DB_CONN_INFO, command_timeout=60) as pool:
async with pool.acquire() as conn:
try:
stmt = await conn.prepare(sql_command)
async with conn.transaction():
for value in data:
async for item in stmt.cursor(*value):
pass
finally:
await pool.release(conn)
test_sql_command = '''
INSERT INTO users(name, dob)
VALUES($1, $2)
ON CONFLICT (name)
DO
UPDATE "users"
SET name = 'TEST'
WHERE name = excluded.name '''
# The name 'HELLO WORLD' exists in the table, but the other name does not.
params = [('HELLO WORLD', datetime.date(1984, 3, 1)),
('WORLD HELLO', datetime.date(1984, 3, 1))]
loop = asyncio.get_event_loop()
loop.run_until_complete(db.insert_new_records(test_sql_command, params))
You need single quotes around the value for name: SET name='TEST'
The double quotes are for table or column names. In your case, you could just remove the double quotes around users.
After edit:
You should really try your SQL commands in the database console, this has nothing to do with python nor async. It's pure postgresql syntax.
So, the second issue in your query is that you shouldn't specify "users" after UPDATE. It's implied that you're updating the same table. So just DO UPDATE SET... is good.
Then, you'll get column reference "name" is ambiguous. You should write DO UPDATE SET name='TEST'. You already are updating the row where name=excluded.name. I am not 100% clear on what you're trying to do. So if you insert a row once, it's inserted as usual. If you insert it a second time, the name is replaced with 'TEST'. The excluded keyword allows you to access the attempted insert values. So for example, if you wanted to update the last_access column when trying to insert an existing name, you would write ON CONFLICT (name) DO UPDATE last_access=excluded.last_access.
you can test
replace :
'''INSERT INTO users(name, dob)
VALUES($1, $2)
ON CONFLICT (name)
DO
UPDATE "users"
SET name = 'TEST'
WHERE name = excluded.name '''
by :
"""INSERT INTO users(name, dob)
VALUES($1, $2)
ON CONFLICT (name)
DO
UPDATE
SET name = 'TEST'
WHERE name = excluded.name """

Updating table based on user input

I created a table with the following details:
myStr2 = "CREATE TABLE Lecturers (lec_no VARCHAR(3), name VARCHAR(30), email VARCHAR(30), PRIMARY KEY(lec_no))"
I then created a function that would be able to update the table.
def update_lecturer(self, field_to_update, value_to_set, lec_no):
self.field_to_update = field_to_update
self.value_to_set = value_to_set
self.lec_no = lec_no
self.myCursor.execute("UPDATE Lecturers SET field_to_update = :field_to_update WHERE lec_no =:lec_no",{'field_to_update':self.field_to_update,'value_to_set':self.value_to_set,'lec_no':self.lec_no})
The table is updated based on the user input:
field_to_update = input("Field update:")
value_to_set = input("Value to set:")
lec_no = input("Lec_no:")
where the field_to_update can be name or email, the value_to_set can be either new value of name or the new value of email.The lec_no is the id of the lecturer whose details we would like to change.
However when I run the my code I get the following error:
sqlite3.OperationalError: no such column: field_to_update
I know there is no such column as field_to_update in my table but how can I set the column to be updated based on user input.
In your last line you should replace the field_to_update with your input and the updated values.
self.myCursor.execute("UPDATE Lecturers SET :field_to_update = :value_to_set ...
(you missed a colon and the actual value_to_set)
I concatenated the variable field_to_update in the update statement then added question marks to represent the other two variables and it worked. Here is my code:
def update_lecturer(self, field_to_update, value_to_set, lec_no):
self.field_to_update = field_to_update
self.value_to_set = value_to_set
self.lec_no = lec_no
self.myCursor.execute("UPDATE Lecturers SET "+self.field_to_update+" = (?) WHERE lec_no = (?)",(self.value_to_set,self.lec_no))
self.myConnection.commit()

python3 psycopg SQL identifier must be string

I am trying to reference dynamic tables and fields in a tkinter GUI project using MySQLdb. Using psycopg2.sql to handle an insert statement.
The user select a code, size and color and inputs a quantity. The table names are made up of the size and the code (eg. size-small and code-1111, table_name=small1111). Then the color is the column name and the quantity is an integer entered into the field. The inputs are saved in a dictionary (tdict) when the user selects them. And the dictionary elements are called to be saved in the database table.
table_name = tdict['Size']+tdict['Code']
stmnt = ("INSERT INTO {} (%s, Date) VALUES(%s, %s)").format(sql.Identifier((table_name, tdict['Color'])))
c.execute(sql.SQL(stmnt, (tdict['Quantity'], date)))
The insert query is giving me a TypeError
TypeError("SQL identifiers must be strings")
Can anyone please help? What am I doing wrong? How should the Identifier be made to behave as a string?
Note: I've tried to pass the Identifier elements through a str class but it didn't work. ie
stmnt = ("INSERT INTO {} (%s, Date) VALUES(%s, %s)").format(sql.Identifier((str(table_name, tdict['Color']))))
You are asking sql.Identifier() to create an identifier out of a tuple, e.g. ('small1111','magenta'). Because format() only substitutes into braces {} (and not %s), I think what you actually had in mind was this:
stmnt = sql.SQL("INSERT INTO {} ({}, Date) VALUES(%s %s)").format( sql.Identifier(table_name), sql.Identifier(tdict['Color']) )
I'd suggest you rethink your database design, though --- you should probably have columns named size, code, and color rather than separate tables and columns for each. That will prevent you from having to add a new column each time a new color or a new table for each new size or code. SELECT count(*) FROM inventory WHERE size = 'small' AND code = '1111' GROUP BY color seems preferable to having to create queries dynamically.
This error message will also appear when you have a typo error where you should have used sql.Literal('someFixedNumber'), but instead using sq.Identifier('someFixedNumber')

How to determine the row id from a column field - SQLite 3, Python

In my SQLite database I have a table called client_dir that is a directory of client contact details. I also have a table called contracts that contains the details of different contracts. I need to be able to create foreign keys that bind a contract entry to a client entry in client_dir.
The thing is , I want to be able to generate the foreign key by just providing the clients name. How do I summon the row id from a field entry?
I think it should look something like this...
def new_contract():
'''creates a new contract entry and links it to a client in the client_dir table'''
client = input("Company name...")
#int(row_id) = client
contract = input("New contract...")
self.cursor.execute("INSERT INTO contracts VALUES (?)",contract,#row_id)
UPDATE
My tables look like this :
self.cursor.execute("""CREATE TABLE client_dir(cli_id INTEGER PRIMARY KEY AUTOINCREMENT, company TEXT, address TEXT, phone INTEGER, email TEXT)""")
self.cursor.execute("""CREATE TABLE contracts(con_id INTEGER PRIMARY KEY AUTOINCREMENT, contract TEXT, client_id INTEGER, FOREIGN KEY(client_id) REFERENCES client_dir(cli_id))""")
and my new _contract method looks like this:
def new_contract(self):
'''creates a new contract entry and links it to a client in the client_dir table'''
client = input("Company name...")
for f_list in self.cursor.execute("SELECT cli_id FROM client_dir WHERE company = (?)",[client]):
f_key = f_list[0]
print(f_key) # For debugging
contract = input("New contract...")
self.cursor.execute("INSERT INTO contracts VALUES (NULL,?,?)",([contract],[f_key]))
print(f_key) is printing a nice tidy 1 on the screen which I am presuming is an int. but I am getting this error:
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
c.new_contract()
File "C:\Python33\smalltime\Client.py", line 63, in new_contract
self.cursor.execute("INSERT INTO contracts VALUES (NULL,?,?)",([contract],[f_key]))
sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type.
I have fixed this now. The error was due to the fact I was passing in the wrong syntax for the INSERT.
The correct last line of the new_contract method should be:
self.cursor.execute("INSERT INTO contracts VALUES (NULL,?,?)",**([contract,f_key]))**
(previously it had two extra braces : ([contract],[f_key]) and that was throwing it out)
so all that remains to do is remove the print statement and add
self.conn.commit()
to the end.

Resources