Raw SQL with "IF NOT EXISTS" doesn't execute - sql-server-2008

This is my python code. It seems that if the raw SQL contains IF NOT EXISTS, sqlalchemy will not execute it. There is no exception thrown either.
db.execute(text(
"""
IF NOT EXISTS ( select 1 from agent_assignment where exception_id = :exception_id )
BEGIN
insert into agent_assignment(exception_id, [user], work_status, insert_date, insert_user)
values (:exception_id, :user, 'pending', :date, :insert_update_user)
END
ELSE
update agent_assignment
set
[user] = :user,
update_date = :date,
update_user = :insert_update_user
where exception_id = :exception_id
"""),
exception_id = exception_id,
user = assignee,
date = datetime.now(),
insert_update_user = insert_update_user
)
If I remove the IF..ELSE part, the SQL will execute correctly. So I guess technically it is impossible to execute the raw SQL with IF..ELSE or EXISTS being a part of the statement?
What is the proper way to run raw SQL?
Thanks in advance.

I need to add COMMIt at the end of the script since the query is kinda complex and somehow sqlalchemy can't auto commit it.

Related

Pulling an Integer value from SQL database to be used for calculation

I am having trouble just trying to pull data out of my table. I just want to pull the integer value from column Diff and add/subtract numbers to it.
Once I am done adding/subtracting, I want to update each row with the new value"
My Table chart for "users" in ruby
This is my code as of now
require 'date'
require 'mysql2'
require 'time'
def test()
connect = Mysql2::Client.new(:host => "localhost", :username => "root", :database => "rubydb")
result = connect.query("SELECT * FROM users where Status='CheckOut'")
if result.count > 0
result.each do |row|
stored_diff = connect.query("SELECT * FROM users WHERE Diff")
#stored_diff = stored_diff.to_s
puts stored_diff
end
end
end
test()
I am sure the code in the hashtag does not work since I am getting like #Mysql2::Result:0x000000000004863248 etc. Can anyone help me with this?
I have no knowledge of ruby but I'll show you the steps to achieve what you are trying based on this and this.
Get User Ids and the Diff numbers.
SELECT `Id`, `Diff` FROM users where `Status`='CheckOut'
Iterate the result.
result.each do |row|
Assign Diff and Id into variables.
usrId = #{row['Id']};
diffCal = #{row['Diff']};
Do your calculations to diffCal variable.
Execute the UPDATE query.
UPDATE `users` SET `Diff` = '#{diffCal}' WHERE `Id` = '#{usrId}'

How can I flush new object and execute DQL in the same transaction?

Can I flush new object (insert) and execute DQL (update some tables) in the same transaction with Doctrine? Or I have to use native SQL query with explicit transaction declaration?
I want to execute something like this in a transaction
INSERT INTO order VALUES (...)
UPDATE user SET email = :email, phone = :phone, status = :status
UPDATE user_counter SET order_counter = order_counter + 1
UPDATE some_counter SET acme_counter = acme_counter + 1
Thank for your help!
Use the wrapInTransaction function of the entityManager. You can mix persist/remove with other DQL queries.
Here's an example:
this->entityManager->wrapInTransaction(function ($em) use($phoneNumber, $phoneNumberVerificationRequest){
$this->entityManager->persist($phoneNumber);
$this->entityManager->flush();
$this->phoneNumberVerificationRequestRepository->removeByCountryCallingCodeAndNumber($phoneNumberVerificationRequest->getCountryCallingCode(), $phoneNumberVerificationRequest->getNumber());
});

Ruby DBI fetch can't handle all-zero dates in MySQL

I'm trying to access our database with some fairly simple CGI/Ruby and DBI:
#!/usr/bin/ruby -w
require "dbi"
dbh = DBI.connect("dbi:Mysql:my:mydb", "XXXX", "XXXX")
...
query = "select ETA from mydb.mytable where ID = #{someval}"
rows = dbh.execute(query)
while row = rows.fetch() do
# Do some stuff
...
end
That works fine most of the time, but I hit a record which broke it with the error:
/usr/lib/ruby/vendor_ruby/dbd/Mysql.rb:120:in `parse': invalid date (ArgumentError)
from /usr/lib/ruby/vendor_ruby/dbd/Mysql.rb:120:in `parse'
from /usr/lib/ruby/vendor_ruby/dbi/row.rb:66:in `block in convert_types'
from /usr/lib/ruby/vendor_ruby/dbi/row.rb:65:in `each'
from /usr/lib/ruby/vendor_ruby/dbi/row.rb:65:in `each_with_index'
from /usr/lib/ruby/vendor_ruby/dbi/row.rb:65:in `convert_types'
from /usr/lib/ruby/vendor_ruby/dbi/row.rb:75:in `set_values'
from /usr/lib/ruby/vendor_ruby/dbi/handles/statement.rb:226:in `fetch'
from /usr/lib/cgi-bin/test:39:in `block in <main>'
from /usr/lib/cgi-bin/test:36:in `each'
from /usr/lib/cgi-bin/test:36:in `<main>'
After a bit of detective work I found that it had a date of 0000-00-00 which fetch() doesn't like. Undefined dates are OK, and DBI in Perl can handle all zero dates, it's just DBI in Ruby.
I can fix the database, and I'll try to get the app which wrote the value to the database fixed too, but I think that my Ruby should be resilient to such things. Is there a way to work around this, maybe using rescue somehow?
This is the solution I came up with:
query = "select ETA from mydb.mytable where ID = #{someval}"
rows = dbh.execute(query)
begin
while row = rows.fetch() do
# Do some stuff
...
end
rescue Exception => e
puts "#{e}<br>\n"
retry
end
This works quite nicely as though the retry is starting a new while loop, rows maintains its state so the fetch resumes on the next record.
The only problem is that it's hard to identify the bad record(s). To fix that I issued more queries without the offending field. My somewhat ugly solution:
results = Hash.new
hit_error = false
query = "select ETA,UNIQUE_ID from mydb.mytable where ID = #{someval}"
rows = dbh.execute(query)
begin
while row = rows.fetch() do
# Do some stuff
...
results[row[1]] = row[0]
end
rescue Exception => e
hit_error = true
retry
end
if hit_error
query = "select UNIQUE_ID from mydb.mytable where ID = #{someval}"
rows = dbh.execute(query)
while row = rows.fetch() do
id = row[0]
unless results.has_key?(id)
begin
query = "select ETA for mydb.mytable where UNIQUE_ID = #{id} limit 1"
error = dbh.execute(query)
error.fetch() # expect this to hit same error as before
puts "Unexpected success for UNIQUE_ID #{id}<br>\n"
rescue Exception => e
puts "#{e} at UNIQUE_ID #{id}<br>\n"
end
end
end
end
Finally I'm not sure how valid it is to use DBI/Ruby, it seems deprecated. Same for MySQL/Ruby. I also tried Sequel with little success.
An alternative solution is to use fetch_hash. This fetches all data as strings, which is a little awkward as you need to convert to dates, integers, etc., but does give you the opportunity of trapping the error on the explicit conversion. This also makes it much easier to identify the bad record(s):
query = "select ETA from mydb.mytable where ID = #{someval}"
rows = dbh.execute(query)
while row = rows.fetch_hash() do
begin
eta = Date.parse row["ETA"]
# Do something with the ETA
...
rescue Exception => e
puts "Error parsing date '#{row["ETA"]}': #{e}<br>\n"
# Make do without the ETA
...
end
end
Sequel can handle invalid dates if you use the mysql adapter:
DB = Sequel.connect('mysql://user:password#host/database')
DB.convert_invalid_date_time = :string # or nil
DB.get(Sequel.cast('0000-00-00', Date))
# => "0000-00-00"

SQLAlchemy MySQL IF Statement

I'm in the middle of converting an old legacy PHP system to Flask + SQLAlchemy and was wondering how I would construct the following:
I have a model:
class Invoice(db.Model):
paidtodate = db.Column(DECIMAL(10,2))
fullinvoiceamount = db.Column(DECIMAL(10,2))
invoiceamount = db.Column(DECIMAL(10,2))
invoicetype = db.Column(db.String(10))
acis_cost = db.Column(DECIMAL(10,2))
The query I need to run is:
SELECT COUNT(*) AS the_count, sum(if(paidtodate>0,paidtodate,if(invoicetype='CPCN' or invoicetype='CPON' or invoicetype='CBCN' or invoicetype='CBON' or invoicetype='CPUB' or invoicetype='CPGU' or invoicetype='CPSO',invoiceamount,
fullinvoiceamount))) AS amount,
SUM(acis_cost) AS cost, (SUM(if(paidtodate>0,paidtodate,invoiceamount))-SUM(acis_cost)) AS profit FROM tblclientinvoices
Is there an SQLAlchemyish way to construct this query? - I've tried googling for Mysql IF statments with SQlAlchemy but drew blanks.
Many thanks!
Use func(documentation) to generate SQL function expression:
qry = select([
func.count().label("the_count"),
func.sum(func.IF(
Invoice.paidtodate>0,
Invoice.paidtodate,
# #note: I prefer using IN instead of multiple OR statements
func.IF(Invoice.invoicetype.in_(
("CPCN", "CPON", "CBCN", "CBON", "CPUB", "CPGU", "CPSO",)
),
Invoice.invoiceamount,
Invoice.fullinvoiceamount)
)
).label("amount"),
func.sum(Invoice.acis_cost).label("Cost"),
(func.sum(func.IF(
Invoice.paidtodate>0,
Invoice.paidtodate,
Invoice.invoiceamount
))
- func.sum(Invoice.acis_cost)
).label("Profit"),
],
)
rows = session.query(qry).all()
for row in rows:
print row

Rails 3. Checking for true values in SQL

I need to check if the column exam has a value of true. So I set this up but it doesn't work...
#exam_shipments = Shipment.where("exam <> NULL AND exam <> 0 AND customer_id = ?", current_admin_user.customer_id)
# This one gives me error "SQLite3::SQLException: no such column: true:"
#exam_shipments = Shipment.where("exam = true AND customer_id = ?", current_admin_user.customer_id)
#exam_shipments = Shipment.where("exam = 1 AND customer_id = ?", current_admin_user.customer_id)
You should really just stick to AR syntax:
#exam_shipments = Shipment.where(:exam => true, :customer_id => current_admin_user.customer_id)
Assuming :exam is a boolean field on your Shipment model. ActiveRecord takes care of converting your query to the proper syntax for the given database. So the less inline SQL you write, the more database-agnostic and portable your code will be.
Why do you need do execute SQL?
It's much easier just to do
#exam_shipments = Shipment.find_by_id(current_admin_user.customer_id).exam?