i want to add multiple rows to table in oracle and get back added values to python list
the returned column is the primary key and is generated on the oracle side
the code I wrote doesn't work, which is understandable, but I don't know how to write otherwise. help me please
out_id = cursor.var(cx_Oracle.NUMBER)
batch = []
for i in range(3):
batch.append({'val': i})
ins = 'INSERT INTO table (col1) VALUES (:val) RETURNING table.col2 into :out_id'
cursor.executemany(ins, batch)
print(list_out_id.getvalue())
I get an error
ORA-01036: illegal variable name/number
#e.burenina
A few observations here:
I am assuming col2 is an AUTO INCREMENT Number field
I am assuming you meant to use out_id instead of list_out_id in the last line
arraysize parameter should be included when you define the cursor variable out-id. i.e., out_id = cursor.var(cx_Oracle.NUMBER,arraysize=3).
cx_Oracle.NUMBER will return any number in Python float format(e.g., 0.0, 1.0 etc.). So if the returned data is an integer,
please use out_id = cursor.var(int,arraysize=3)
The batch list should include both the input 'val' and the output variable out_id
batch.append({'val':i,'out_id':out_id})
The following code should return the required values:
import cx_Oracle
# Establish the database connection - Add your DB details here
connection = cx_Oracle.connect(user="hr", password="hr", dsn="localhost/orclpdb")
# Obtain a cursor
cursor = connection.cursor()
# set the input and output variables
out_id = cursor.var(int, arraysize=3)
batch = []
for i in range(3):
batch.append({'val': i, 'out_id': out_id})
# set the SQL statement
ins = 'INSERT INTO table(col1) VALUES (:val) RETURNING table.col2 into :out_id'
# run the query and fetch the output into 'out_id' variable
cursor.executemany(ins, batch)
# print the out_id in a list
print(out_id.values)
Note: Please ensure that you do a connection.commit() at the end, in case you want to commit your code changes to the DB
Also make changes to the arraysize parameter based on the number of rows returned by your INSERT statement.
For printing output in the format
[{'val': 1, 'out_id': id_1}, {'val': 2, 'out_id': id_2}, {...}]
the following code will work
import cx_Oracle
# Establish the database connection - Add your DB details here
connection = cx_Oracle.connect(
user="hr", password="hr", dsn="localhost/orclpdb")
# Obtain a cursor cursor = connection.cursor()
# set the input and output variables
out_id = cursor.var(int, arraysize=3)
batch = []
for i in range(3):
batch.append({'val': i, 'out_id': out_id})
# set the SQL statement
ins = 'INSERT INTO table(col1) VALUES (:val) RETURNING table.col2 into :out_id'
# run the query and fetch the output into 'out_id' variable
cursor.executemany(ins, batch)
#print the output in the required format
for i in range(3):
batch[i]['out_id'] = batch[i]['out_id'].getvalue(i)
print(batch)
print(out_id.values)
# Do a commit to the table if required
# connection.commit()
Related
I read a column's length in the code given below. Then, I have a list fakeNames whose length is equal to the column's original length.
How can I replace the values of the original column person_nameswith my list fakeNamesvalues? The changes should be reflected in the database.
import MySQLdb
# Connect
db = MySQLdb.connect(
host="abc.us-east-1.rds.amazonaws.com",
user="abc",
password="password",
)
cursor = db.cursor()
# Execute SQL select statement
cursor.execute("SELECT COUNT(person_names) FROM z3_table")
number_of_names = (cursor.fetchone()[0])
print(number_of_names)
fakeNames = []
# Commit your changes if writing
# In this case, we are only reading data
# db.commit()
# Close the connection
db.close()
This means that each value from the list fakeNamesshould be in a different row.
I was playing around with SQLalchemy and Microsoft SQL Server to get a hang of the functions when I came across a strange behavior. I was taught that the attribute rowcount on the result proxy object will tell how many rows were effected by executing a statement. However, when I select or insert single or multiple rows in my test database, I always get -1. How could this be and how can I fix this to reflect the reality?
connection = engine.connect()
metadata = MetaData()
# Ex1: select statement for all values
student = Table('student', metadata, autoload=True, autoload_with=engine)
stmt = select([student])
result_proxy = connection.execute(stmt)
results = result_proxy.fetchall()
print(result_proxy.rowcount)
# Ex2: inserting single values
stmt = insert(student).values(firstname='Severus', lastname='Snape')
result_proxy = connection.execute(stmt)
print(result_proxy.rowcout)
# Ex3: inserting multiple values
stmt = insert(student)
values_list = [{'firstname': 'Rubius', 'lastname': 'Hagrid'},
{'firstname': 'Minerva', 'lastname': 'McGonogall'}]
result_proxy = connection.execute(stmt, values_list)
print(result_proxy.rowcount)
The print function for each block seperately run example code prints -1. The Ex1 successfully fetches all rows and both insert statements successfully write the data to the database.
According to the following issue, the rowcount attribute isn't always to be trusted. Is that true here as well? And when, how can I compensate with a Count statement in a SQLalcehmy transaction?
PDO::rowCount() returning -1
The single-row INSERT … VALUES ( … ) is trivial: If the statement succeeds then one row was affected, and if it fails (throws an error) then zero rows were affected.
For a multi-row INSERT simply perform it inside a transaction and rollback if an error occurs. Then the number of rows affected will either be zero or len(values_list).
To get the number of rows that a SELECT will return, wrap the select query in a SELECT count(*) query and run that first, for example:
select_stmt = sa.select([Parent])
count_stmt = sa.select([sa.func.count(sa.text("*"))]).select_from(
select_stmt.alias("s")
)
with engine.connect() as conn:
conn.execution_options(isolation_level="SERIALIZABLE")
rows_found = conn.execute(count_stmt).scalar()
print(f"{rows_found} row(s) found")
results = conn.execute(select_stmt).fetchall()
for item in results:
print(item.id)
I've been trying to use this piece of code:
# df is the dataframe
if len(df) > 0:
df_columns = list(df)
# create (col1,col2,...)
columns = ",".join(df_columns)
# create VALUES('%s', '%s",...) one '%s' per column
values = "VALUES({})".format(",".join(["%s" for _ in df_columns]))
#create INSERT INTO table (columns) VALUES('%s',...)
insert_stmt = "INSERT INTO {} ({}) {}".format(table,columns,values)
cur = conn.cursor()
cur = db_conn.cursor()
psycopg2.extras.execute_batch(cur, insert_stmt, df.values)
conn.commit()
cur.close()
So I could connect into Postgres DB and insert values from a df.
I get these 2 errors for this code:
LINE 1: INSERT INTO mrr.shipments (mainFreight_freight_motherVesselD...
psycopg2.errors.UndefinedColumn: column "mainfreight_freight_mothervesseldepartdatetime" of relation "shipments" does not exist
for some reason, the columns can't get the values properly
What can I do to fix it?
You should not do your own string interpolation; let psycopg2 handle it. From the docs:
Warning Never, never, NEVER use Python string concatenation (+) or string parameters interpolation (%) to pass variables to a SQL query string. Not even at gunpoint.
Since you also have dynamic column names, you should use psycopg2.sql to create the statement and then use the standard method of passing query parameters to psycopg2 instead of using format.
I am currently trying to get a list of values from a table inside an SQL database. The problem is appending the values due to the table's name in which I can't change. The table's name is something like Value123/123.
I tried making a variable with the name like
x = 'Value123/123'
then doing
row.append(x)
but that just prints Value123/123 and not the values from the database
cursor = conn.cursor()
cursor.execute("select Test, Value123/123 from db")
Test = []
Value = []
Compiled_Dict = {}
for row in cursor:
Test.append(row.Test)
Value.append(row.Value123/123)
Compiled_Dict = {'Date&Time': Test}
Compiled_Dict['Value'] = Value
conn.close()
df = pd.DataFrame(Compiled_Dict)
The problem occurs in this line
Value.append(row.Value123/123)
When I run it I get that the database doens't have a table named 'Value123'. Since I think it's trying to divide 123 by 123? Unfortunately the table in the database is named like this and I cannot change it, so how do I pull the values from this table?
Edit:
cursor.execute("select Test, Value123/123 as newValue from db")
I tried this and it worked thanks for the solutions. Suggested by Yu Jiaao
I am new to Python, so need some help in this concern:
Here I am trying to insert the values in the database, when I tried giving the hard coded values then insertion taking place,
Note: common_test2 has only 2 words
But when I am writing like below:
import cx_Oracle
con = cx_Oracle.connect('sys/sys#127.0.0.1:1599/xe')
print(con.version) //just to check the connection
print("this connection is established") //connection is tested
cur=con.cursor()
f3= open("common_test2", 'r+')
string= f3.read()
common_words=string.split()
x=common_words[0]
y=common_words[1]
cur.execute("INSERT INTO test(name,id) VALUES (%s,%d)", ('hello',30))
con.commit()
Error is
Error is cx_Oracle.DatabaseError: ORA-01036: illegal variable name/number
Also tried cur.execute("INSERT INTO test(name,id) VALUES (x, y)")
but no luck
Error is cx_Oracle.DatabaseError: ORA-00984: column not allowed here
Any help?
#I am using this for updating the table
y=100%
x=text
cur.execute("update temp set perc=(:1)", (y))
#Please note: I only want 100 to be updated in the table not the % (only 100 as numeric)
cur.execute("update temp set remarks=(:1)",(x))
Error comes from here:
cur.execute("INSERT INTO test(name,id) VALUES (%s,%d)", ('hello',30))
Try to use :n pointers:
cur.execute("INSERT INTO test(name, id) VALUES (:1, :2)", ('hello', 30))
update
For your second case - if y is a string like y = "100%", then you can make update this way:
cur.execute("update temp set perc = :1", (y[:-1],))
This will insert 100 as an int.
Note that 1-item sized tuple is (x,), not (x).
Code I'm Using
import cx_Oracle
con = cx_Oracle.connect('system/system#127.0.0.1:1521/xe')
# print(con.version)
#
# print("this connection is established")
cur = con.cursor()
f3 = open("common.txt", 'r+') #this text file have only 2 words lets say (10% increased)
string = f3.read() #will read common.txt
common_words = string.split()
x = common_words[0] #here x have 10%
y = common_words[1] #here y have increased
# Now I want 10 should be updated in the temp table **Not 10%**
cur.execute("update temp set perc=(:1)", (y[:-1],))
cur.execute("update temp set remarks=(:1)", (y))
con.commit
Note: I have to retrieve that 10 and do further calculations
Table Temp:
perc remarks
10 increased