How to use column name dynamically inside insert query in djnago - python

cursor.execute("insert into demoapp_site ('name','firstname','lastname') values (%s,%s,%s)",site_data)
in above query I want to pass column name dynamically and %s which is inside values also not predefine that how many times it need to write
so, how can I write my sql query according to my data which comes from html table in 2d array from??

We need to build the query before using it. As follows
field_string = ""
value_string = ""
# This will string in this format "'field1','field2'"
# Assuming array is in format [["field1", "value1"],..]
# Update the for loop statement based on your input, other lines remain same
for field, value in my_field_array:
temp_field_string = "'%s'" % field
field_string = field_string + temp_field_string + ","
temp_value_string = "'%s'" % value
value_string = value_string + temp_value_string + ","
# Removing trailing comma's before passing the values
cmd = "insert into demoapp_site (%s) values (%s)" % (field_string[:-1], value_string[:-1])
cursor.execute(cmd)

Related

String extraction & formatting for SQL snippet execution

I have a few parameters typed in a string that need to be extracted & substituted using the string format() function. The code snippet is as follows:
# Filter list (output from another script)
filters ='recipient_id=100, reporting_date=2020-10-12'
# Fetch SQL file from location
sql_file = 'configs/sql_files/{sql_name}.sql'.format(sql_name=sql_name)
file_path = os.path.realpath(__file__)
final_file_path = "/".join(file_path.split("/")[:-2]) + "/" + sql_file
with open(final_file_path) as sql_file:
# Pass in filters to the SQL snippet. The SQL snippet has two parameters
# recipient_id & reporting_date
sql = sql_file.read().format(filters)
try:
sf = get_sql_client()
except Exception as e:
print("Error connecting to the DB!")
sys.exit()
df = sf.fetch_df(sql)
The code snippet fails as "filters" is being passed as a string.
sql_file.read().format('recipient_id=100, reporting_date=2020-10-12')
Instead, it should be passed as below:
sql_file.read().format(recipient_id=100, reporting_date='2020-10-12')
Is there a way to extract the "filters" string & format it as above?
SQL file sample:
SELECT columns..
FROM A
join B on <condition>
WHERE true
AND REPORTING_LEVEL_1_ID = '{recipient_id}'
AND date_trunc('day', delivered_date_pt) >= DATEADD(day, -7, last_day('{reporting_date}'::date, 'week') + 1)
AND date_trunc('day', delivered_date_pt) <= last_day('{reporting_date}'::date, 'week')
try using double quotes like so...
filters ="recipient_id=100, reporting_date='2020-10-12'"
Assuming the sql file with contents like that and for filtering information formatting as shown (as a series of name and value pairs, separated by comma and space characters), you could create dictionary from the latter and then pass it to the format() method as shown (using a ** prefix to unpack the items in it).
filter_data = 'recipient_id=100, reporting_date=2020-10-12'
final_file_path = 'sql_file'
with open(final_file_path) as sql_file:
pairs = (pair.split('=') for pair in filter_data.replace(',', '').split())
mapping = {k: v for (k, v) in pairs}
sql = sql_file.read().format(**mapping)
print(sql)
Output:
SELECT columns..
FROM A
join B on <condition>
WHERE true
AND REPORTING_LEVEL_1_ID = '100'
AND date_trunc('day', delivered_date_pt) >= DATEADD(day, -7, last_day('2020-10-12'::date, 'week') + 1)
AND date_trunc('day', delivered_date_pt) <= last_day('2020-10-12'::date, 'week')

How to put a $ before a value taken from a database through SQL in Python

I'm trying to display values in HTML that have a "$" at the beginning, but the way I print out the values in HTML makes it so that with the justification I can only add it at the end of the previous value or at the end of the value.
I'm thinking I have to somehow incorporate the "$" into the for loop, but I'm not sure how to do that.
BODY['html'] += '<br>Total shipped this month:..............Orders........Qty...........Value<br>'
SQL5 = '''
select count(*) as CNT, sum(A.USER_SHIPPED_QTY) as QTY, sum(( A.USER_SHIPPED_QTY) * A.UNIT_PRICE) as VALUE
from SHIPPER_LINE A, SHIPPER B
where B.PACKLIST_ID = A.PACKLIST_ID
and A.CUST_ORDER_ID like ('CO%')
and B.SHIPPED_DATE between ('{}') and ('{}')
'''.format(RP.get_first_of_cur_month_ora(), RP.get_rep_date_ora())
## {} and .format get around the issue of using %s with CO%
print SQL5
curs.execute(SQL5)
for line in curs: ##used to print database lines in HTML
print line
i=0
for c in line:
if i==0:
BODY['html'] += '<pre>' + str(c).rjust(60,' ')
elif i == 1:
BODY['html'] += str(c).rjust(15,' ')
else:
BODY['html'] += str(c).rjust(22,' ') + '</pre>'
i+=1
The "pre" in HTML is used to keep the whitespace and the ' ' after rjust is used to space the numbers properly to go under the column headings. The values that are printed out are generated from the database using the SQL.
Here is what displays in HTML for this code:
Total shipped this month:..............Orders........Qty...........Value
3968 16996 1153525.96
This is what I want it to look like:
Total shipped this month:..............Orders........Qty...........Value
3968 16996 $1153525.96
You could apply the format in the DB by wrapping your sum with a to_char and a currency/numeric format model ...
select to_char(12345.67, 'FML999,999.99') FROM DUAL;

Python: Iterating through MySQL columns

I'm wondering if you can help me. I'm trying to change the value in each column if the text matches a corresponding keyword. This is the loop:
for i in range(0, 20, 1):
cur.execute("UPDATE table SET %s = 1 WHERE text rlike %s") %(column_names[i], search_terms[i])
The MySQL command works fine on its own, but not when I put it in the loop. It's giving an error at the first %s
Does anyone have any insights?
This is the error:
_mysql_exceptions.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 '%s = 1 WHERE text rlike %s' at line 1")
Column names looks like
column_names = ["col1","col2","col3"...]
Search terms look like
search_terms = ["'(^| |.|-)word1[;:,. ?-]'","'(^| |.|-)word2[;:,. ?-]'",...]
The right way to do this is to give values to Python, which will quote things correctly.
adapted from voyager's post:
for i in range(0, 20, 1):
cur.execute("UPDATE table SET {} = 1 WHERE text rlike %s".format(column_names[i]),
(search_terms[i],),
)
In this case it's confusing because the column_name isn't a value, it's part of the table structure, so it's inserted using good old string formatting. The search_term is a value, so is passed to cursor.execute() for correct, safe quoting.
(Don't use string manipulation to add the quotes -- you're exposing yourself to SQL injection.)
Missing quotes and wrong parenthesis placement...
for i in range(0, 20, 1):
cur.execute("UPDATE table SET %s = 1 WHERE text rlike '%s'" %(column_names[i], search_terms[i]))
# ^ ^
# (-----------------------------------------------------------------------------------)
Please note, this is not the right way of doing this, if your string may contain quotes by itself...
What about that instead:
for i in range(0, 20, 1):
cur.execute("UPDATE table SET %s = 1 WHERE text rlike ?" % (column_names[i],),
(search_terms[i],))
This uses the % operator to set the column name, but uses an executes parameter to bind the data, letting the DB driver escape all characters that need so.

Generating a list of names in python from mysql

I currently am able to generate a text file with the information but for some reason i can not send the data to go into a list. i have tried it 2 ways:
cnx = mysql.connector.connect(user='root', database='smor')
cursor = cnx.cursor()
sqlQuery = ("SELECT id,name,CAST(aa_seq as CHAR(65535)) aa_seq FROM smor.domain_tbl WHERE domain_type_id=5 AND domain_special IS NULL LIMIT 100000")
cursor.execute(sqlQuery)
print "Generating FASTA file: ", FASTA_File1
with open(FASTA_File1, "w") as FASTA1:
for (aa_id, name, aa_seq) in cursor:
FASTA1.write(">" + name + '\n' + aa_seq + '\n')
print ">" + name + '\n' + aa_seq
ListOfNames =[]
for (aa_id, name, aa_seq) in cursor:
ListOfNames.append(name)
cursor.close()
print "ListOfNames", ListOfNames
this successfully prints the name and amino acid sequence into the text file but the string is empty. here are the last lines of the output in the console:
>NC_018581.1_05_011_001_020 P
RVPGEMYERAEDGALIPTGVRARWVDAPGSRREIVGPIARHPRIDGRRVDLDVVEEALAAVTGVTAAAVVGLPTDDGVEVGACVVLDRDDLDVPGLRRELSQTLAAHCVPTMISIVESIPLGTDGRPDHGEV
ListOfNames []
As you can see the list remains empty. I thought that perhaps the cursor could not jump back up to the top so i closed the cursor and reopened it exactly as above but with the list generation in the second instance. this caused an error in the script and i do not know why.
Is it that the data can not be read directly into a list?
Theoretically i can split the names of the sequences back out of the text file but i am curious why this method is not working.
As you suspect, the cursor's result set can be read once, after which it is 'consumed'.
Just put the result inside the list first, then iterate over the list to write it's content to the file. Or do both in one loop.

IndexError string index out of range when referencing first character

Here is my code (currently):
conn = sqlite3.connect(db)
conn.text_factory = str #bugger 8-bit bytestrings
cur = conn.cursor()
reader = csv.reader(open(csvfile, "rU"), delimiter = '\t')
for Number, Name, Message, Datetime, Type in reader:
# populate subscriber table
if str(Number)[0] == '1': # errors on this line
tmpNumber = str(Number)[1:]
Number = int(tmpNumber)
cur.execute('INSERT OR IGNORE INTO subscriber (name, phone_number) VALUES (?,?)', (Name, Number))
cur.close()
conn.close()
It returns this error on the line commented to indicate where the error lies:
IndexError: string index out of range
All of the numbers have values, but if the phone number starts with a 1 I want to remove the 1 before inserting it into the database. Why won't this work? I've converted it to a string before trying to reference the first character, so I don't understand why this isn't working.
Seems like you are getting an empty string. Try replacing your if statement with the following and see if it works.
if str(Number).startswith('1'):
(Edited to reflect #kindall 's suggestion of using startswith instead of slicing [:1]).

Categories