2

In my Rails 4 app I need to find all plans that do either have an interval of month OR an amount of 0.

This doesn't work:

class Plan < ActiveRecord::Base def self.by_interval(interval) where("interval = ? OR amount = ?", interval, 0) end end 

I am getting this error:

Mysql2::Error: 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 '= 'month' OR amount = 0) ORDER BY amount DESC' at line 1: SELECT `plans`.* FROM `plans` WHERE (interval = 'month' OR amount = 0) ORDER BY amount DESC 

What else might work?

Thanks for any help.

6
  • I think you have a type issue. Would have been helpfull if you posted the syntax error. I guess your interval is a string. so try: where("interval like '?' OR amount = ?", interval, 0) Commented Jan 1, 2015 at 20:58
  • Tried that but didn't work. The syntax errors I am getting all look similar: Mysql2::Error: 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 'LIKE ''month'' OR amount = 0)' at line 1: SELECT plans.* FROM plans WHERE (interval LIKE ''month'' OR amount = 0) Commented Jan 1, 2015 at 21:09
  • sorry, remove the single quotes again and update your question with the original syntax error please. Commented Jan 1, 2015 at 21:18
  • Okay. Update posted above. Commented Jan 1, 2015 at 21:31
  • What datatype is interval? Is it a kind of string/text/varchar? Commented Jan 1, 2015 at 21:58

3 Answers 3

2

'interval' in mysql is a reserved word (http://dev.mysql.com/doc/refman/5.6/en/reserved-words.html).

Try it like this:

def self.by_interval(interval) where("`interval` = ? OR amount = ?", interval, 0) end 

note the backticks around "interval" (not quotes)

Sign up to request clarification or add additional context in comments.

2 Comments

Wow, surprisingly that finally works! Thank you. I just wonder if I should better rename the column to something else if interval is a reserved word.
Looks like this is only a problem if you write your queries like this yourself. If you do things like "where(:interval => interval)" Rails already handles it in the generated sql. So I don't think renaming is necessary.
1

Since you're not doing an exclusive or, but an inclusive, I would do it in two requests:

class Plan < ActiveRecord::Base def self.by_interval(interval) where(interval: interval) << where(amount: 0) end end 

These are both arrays of results and the second set of results get injected into the first. I do realize this is two separate requests so it might not be as optimized as you'd like.

I believe using Rails ActiveRecord caching may be a way to save on a performance hit. I don't know if it's done automatically for you in this case, or if you should load the full table request before the queries are performed.

Comments

-1

Just pass the arguments directly into the strings

def self.by_interval(interval) where("interval = #{interval} OR amount = 0") end 

4 Comments

I'm not sure why this answer was downvoted, but if your interval variable is a string you just have to wrap it with single quotes
Thanks, but both suggestions didn't work. I keep getting MySQL syntax errors.
@boulder_ruby I didn't downvote, but perhaps one reason is that adding interpolated values in SQL could result in SQL Injection vulnerabilities. I think your answer is correct, but would be improved by where("interval = ? OR amount = 0", interval) to avoid this issue.
I know this isn't a good answer, but maybe "Switch to PostgreSQL" (or SQLite3) is your best solution

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.