Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Help w/ SQL statement to SQLite3 DB in Ruby 1.9.1

Posted on 2010-08-13
15
Medium Priority
?
620 Views
Last Modified: 2012-06-21
Hey All,

I'm a total Ruby beginner and nearly an SQL beginner. I'm working on exercises from the book "Beginning Ruby - From Novice to Professional."

The current exercise is a simple little CRUD app, connecting to an SQLite3 db. Here's a line that's giving me trouble:

$db.execute("INSERT INTO people (job, name, gender, age) VALUES (?,?,?,?)", job, name, gender, age) 

Open in new window


When this line executes, it always makes the first value (name, in this case) nil. I've swapped 'name' and 'job' (in both places) and then 'job' comes out nil when I display all records with "SELECT * FROM..."

Can anyone tell me what I'm doing wrong and why it's not taking the first parameter?

Thanks,
Bret
0
Comment
Question by:FOS-Bret
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 7
15 Comments
 
LVL 60

Expert Comment

by:Kevin Cross
ID: 33433993
Maybe there is a type conversion issue or other problem in structure of table as that appears to be the valid Ruby command afaik. Please post the create statement for the table.
0
 
LVL 13

Expert Comment

by:darren-w-
ID: 33434033
Try placing the string values in speech marks

$db.execute("INSERT INTO people (job, name, gender, age) VALUES (?,?,?,?)",' job, name, gender', age)


0
 
LVL 60

Expert Comment

by:Kevin Cross
ID: 33434065
I figured those for variables and not literals, since the format string (parameterized string) approach was being used. If those are indeed string literals then you should include proper quoting. For Ruby it appears that is " from what I have seen so:

$db.execute("INSERT INTO people (job, name, gender, age) VALUES (?,?,?,?)", "job", "name", "gender", "age")

Or more appropriate to data types:
$db.execute("INSERT INTO people (job, name, gender, age) VALUES (?,?,?,?)", "a job", "john doe", "male", 50)
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:FOS-Bret
ID: 33434278
Sorry. I didn't make it clear before.

job, name, gender, and age are variables that get set before that statement with gets statements.

For example:

job = gets.chunk
name = gets.chunk
gender = gets.chunk
age = gets.chunk

Age gets put into the DB like...

age.to_i

The others just get put in as strings.

Anyway, if I put quotes around job, name, gender, and age, wouldn't that put those literal strings in instead of the values contained in those variables?

Thanks,
Bret
   
0
 
LVL 60

Expert Comment

by:Kevin Cross
ID: 33434348
Correct. Only do that if passing literals. Have you tried that by the way? Can you try inserting a row directly in SQLite also and see what happens.
0
 

Author Comment

by:FOS-Bret
ID: 33434386
mwvisa1,
I'll try that on Monday as the system is at work and I'm done for the weekend.
Thanks,
Bret
0
 

Author Comment

by:FOS-Bret
ID: 33440886
Hey All,

I was able to RC into my work computer today to try the suggestions.

It's not the variables, because using literals instead produces the same result. Here's the code for the create_table and add_person methods. For the test in add_person, I commented out the original $db.execute line and added the one w/ the literals.

[code]
def create_table
  puts "Creating people table"
 
  $db.execute %q{
  CREATE TABLE people (
  id integer primary key,
  name varchar(50),
  job varchar(50),
  gender varchar(6),
  age integer)
  }
end

def add_person
  puts "Enter Name: "
  name = gets.chomp
  puts "Enter Job: "
  job = gets.chomp
  puts "Enter Gender: "
  gender = gets.chomp
  puts "Enter Age: "
  age = gets.chomp
  puts "Name: #{name}"
  # $db.execute("INSERT INTO people (job, name, gender, age) VALUES (?,?,?,?)", job, name, gender, age)
  $db.execute("INSERT INTO people (job, name, gender, age) VALUES (?,?,?,?)", "Male Escort", "Fred Garvin", "Male", 42)
end
[/code]

Thanks,
Bret
0
 
LVL 60

Expert Comment

by:Kevin Cross
ID: 33440907
Have you checked that the table is actually created in SQLite, since it appears you are doing this via the Ruby code also? Note that if the table already exists with wrong structure, this statement will fail. You would need to drop the original table and recreate ; however, that is typically not what is desired as that would remove original data, so I would suggest moving this portion from your code and doing once directly in SQLite or put "delete table if exists people;" before the create table bit.

After you check on the table in SQLite, try running a regular insert statement from command line and ensure that is functioning.
0
 

Author Comment

by:FOS-Bret
ID: 33440951
Thanks. I've been deleting the file called "dbfile" each time before I run the code just in case, so I know it's gone. I put a puts statement at the beginning for debugging, and when I delete the db file, the app fails because I always forget to comment out that line. So, I know the table is being recreated each time.

Here's the entire program.

Thanks,
Bret

======


require 'rubygems'
require 'sqlite3'
$db = SQLite3::Database.new("dbfile")
$db.results_as_hash = true

def disconnect_and_quit
  $db.close
  puts "Bye."
  exit
end

def create_table
  puts "Creating people table"
  
  $db.execute %q{
  CREATE TABLE people (
  id integer primary key,
  name varchar(50),
  job varchar(50),
  gender varchar(6),
  age integer)
  }
end

def add_person
  puts "Enter Name: "
  name = gets.chomp
  puts "Enter Job: "
  job = gets.chomp
  puts "Enter Gender: "
  gender = gets.chomp
  puts "Enter Age: "
  age = gets.chomp
  puts "Name: #{name}"
  # $db.execute("INSERT INTO people (job, name, gender, age) VALUES (?,?,?,?)", job, name, gender, age)
  $db.execute("INSERT INTO people (job, name, gender, age) VALUES (?,?,?,?)", "Male Escort", "Fred Garvin", "Male", 42)
end

def find_person
  puts "Enter name or ID of person to find: "
  id = gets.chomp
  person = $db.execute("SELECT * FROM people WHERE name = ? OR id = ?", id, id.to_i).first
  unless person
    puts "No result found."
    return
  end
  puts %Q{Name: #{person['name']}
  Job: #{person['job']}
  Gender: #{person['gender']}
  Age: #{person['age']}}
end
 puts $db.execute("SELECT * FROM people")
loop do
  puts %q{Please select an option:

  1. Create people table.
  2. Add a person.
  3. Look for a person.
  4. Quit.}

  case gets.chomp
  when '1'
    create_table
  when '2'
    add_person
  when '3'
    find_person
  when '4'
    disconnect_and_quit
  end
end

Open in new window

0
 
LVL 60

Expert Comment

by:Kevin Cross
ID: 33440988
Have a theory, try this:
require 'rubygems'
require 'sqlite3'
$db = SQLite3::Database.new("dbfile")
$db.results_as_hash = true

def disconnect_and_quit
  $db.close
  puts "Bye."
  exit
end

def create_table
  puts "Creating people table"
  
  $db.execute %q{
  CREATE TABLE people (
  id integer primary key autoincrement,
  name varchar(50),
  job varchar(50),
  gender varchar(6),
  age integer)
  }
end

def add_person
  puts "Enter Name: "
  name = gets.chomp
  puts "Enter Job: "
  job = gets.chomp
  puts "Enter Gender: "
  gender = gets.chomp
  puts "Enter Age: "
  age = gets.chomp
  puts "Name: #{name}"
  # $db.execute("INSERT INTO people (job, name, gender, age) VALUES (?,?,?,?)", job, name, gender, age)
  $db.execute("INSERT INTO people (job, name, gender, age) VALUES (?,?,?,?)", "Male Escort", "Fred Garvin", "Male", 42)
end

def find_person
  puts "Enter name or ID of person to find: "
  id = gets.chomp
  person = $db.execute("SELECT * FROM people WHERE name = ? OR id = ?", id, id.to_i).first
  unless person
    puts "No result found."
    return
  end
  puts %Q{Name: #{person['name']}
  Job: #{person['job']}
  Gender: #{person['gender']}
  Age: #{person['age']}}
end
 puts $db.execute("SELECT * FROM people")
loop do
  puts %q{Please select an option:

  1. Create people table.
  2. Add a person.
  3. Look for a person.
  4. Quit.}

  case gets.chomp
  when '1'
    create_table
  when '2'
    add_person
  when '3'
    find_person
  when '4'
    disconnect_and_quit
  end
end

Open in new window

0
 

Author Comment

by:FOS-Bret
ID: 33443142
Sorry. No luck.

I figured out that I could pass info for ALL columns (including the "id" column by specifying "nil" for that column value and letting Ruby (or SQLite3) fill in the autonumber. For example:

$db.execute( "INSERT INTO people values ( ?, ?, ?, ?, ? )", nil, name, job, gender, age )

That worked, but the point of the exercise is that you don't have to specify ALL column names. So I should be able to do something like the original line of code, but for some reason it accepts all values except the first and makes that one a nil.

I'm still dumbfounded.

Thanks,
Bret
0
 
LVL 60

Expert Comment

by:Kevin Cross
ID: 33443170
Yeah, it doesn't make sense. My theory was that you were originally creating the id column without the autoincrement keyword but specified as primary key I was wondering if it was requiring that column be non-null and therefore causing your first column to be null somehow (though that still didn't make sense to me it was worth the try) ...

Not as good with Ruby, so do you know if this is valid?

$db.execute( "INSERT INTO people(job, name, gender, age) values ( '?', '?', '?', ? )", name, job, gender, age )

Or will it read that as literal ? ...
0
 

Author Comment

by:FOS-Bret
ID: 33448602
Hey,

Yeah, it bombed w/ the statement as is, but it took them as literals when I removed the variables on the end. Kicking points up to 500.

Thanks,
Bret
0
 

Accepted Solution

by:
FOS-Bret earned 0 total points
ID: 33459369
OK. I found the answer here:

http://www.eggheadcafe.com/software/aspnet/36149991/sqlite-placeholder-problem.aspx

Basically, you have to pass the variables in an array rather than one-by-one. So, the following line:

$db.execute("INSERT INTO people (job, name, gender, age) VALUES (?,?,?,?)", job, name, gender, age)

becomes:

$db.execute("INSERT INTO people (job, name, gender, age) VALUES (?,?,?,?)", [job, name, gender, age])

It's working fine now. Thanks for the effort. I appreciate it.

-Bret
0
 
LVL 60

Expert Comment

by:Kevin Cross
ID: 33460006
Glad you found that and thanks for posting for others in the Ruby community. My skill set is on the database side, so I wouldn't have probably made that connection, so I am glad to have learned something new myself. :)

Thanks!

Best regards,
Kevin
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

As they say in love and is true in SQL: you can sum some Data some of the time, but you can't always aggregate all Data all the time! Introduction: By the end of this Article it is my intention to bring the meaning and value of the above quote to…
Confronted with some SQL you don't know can be a daunting task. It can be even more daunting if that SQL carries some of the old secret codes used in the Ye Olde query syntax, such as: (+)     as used in Oracle;     *=     =*    as used in Sybase …
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…
Suggested Courses

604 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question