SQLite not printing - sql

I'm trying to learn SQL through "Learn SQL the Hard Way" and I am having difficulty with the the command prompt. In particular, I am having trouble with the 3rd exercise.
I am able to create a database from ex2.sql by calling
sqlite3 ex3.db < ex2.sql
This should build a database with the schema:
CREATE TABLE person (
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT,
age INTEGER
);
CREATE TABLE pet (
id INTEGER PRIMARY KEY,
name TEXT,
breed TEXT,
age INTEGER,
dead INTEGER
);
CREATE TABLE person_pet (
person_id INTEGER,
pet_id INTEGER
);
Calling .schema on sqlite3 ex3.db prints out exactly this.
Then I use ex3.sql which has the contents:
INSERT INTO person (id, first_name, last_name, age)
VALUES (0, "Zed", "Shaw", 37);
INSERT INTO pet (id, name, breed, age, dead)
VALUES (0, "Fluffy", "Unicorn", 1000, 0);
INSERT INTO pet VALUES (1, "Gigantor", "Robot", 1, 1);
I insert to ex3.db by saying:
sqlite3 -echo ex3.db < ex3.sql
According to the book, this should insert the values from ex3.sql into ex3.db while printing out what it is doing. However, when I type the above into cmd it prints nothing. And when I call
sqlite3 ex3.db
select * from person;
it still shows nothing. My guess is that either the database file is not updating, something with my install went wrong, or I'm messing something else up here. Appreciate any help that can be given.

The command:
sqlite3 -echo ex3.db < ex3.sql
Is used to print what is in the ex3.sql file as it is executed. If nothing is displayed then nothing will be in the file! This means that it will be a problem with the ex3.sql file, such that it is either empty or corrupt.

Related

INSERT + SELECT data type mismatch on similar fields

I'm running the following SQLite workaround to add a primary key to a table that did not have one. I am getting a datatype mismatch on
INSERT INTO cities
SELECT id, name FROM old_cities;
However, the fields have exactly the same type. Is it possible that his happens due to running the queries from DbBrowser for SQLite?
CREATE table cities (
id INTEGER NOT NULL,
name TEXT NOT NULL
);
INSERT INTO cities (id, name)
VALUES ('pan', 'doul');
END TRANSACTION;
PRAGMA foreign_keys=off;
BEGIN TRANSACTION;
ALTER TABLE cities RENAME TO old_cities;
--CREATE TABLE cities (
-- id INTEGER NOT NULL PRIMARY KEY,
-- name TEXT NOT NULL
--);
CREATE TABLE cities (
id INTEGER NOT NULL,
name TEXT NOT NULL,
PRIMARY KEY (id)
);
SELECT * FROM old_cities;
INSERT INTO cities
SELECT id, name FROM old_cities;
DROP TABLE old_cities;
COMMIT;
You have defined the column id of the table cities to be INTEGER, but with this:
INSERT INTO cities (id, name) VALUES ('pan', 'doul');
you insert the string 'pan' as id.
SQLite does not do any type checking in this case and allows it.
Did you mean to insert 2 rows each having the names 'pan' and 'doul'?
If so, you should do something like:
INSERT INTO cities (id, name) VALUES (1, 'pan'), (2, 'doul');
Later you rename the table cities to old_cities and you recreate cities but you do something different: you define id as INTEGER and PRIMARY KEY.
This definition is the only one that forces type checking in SQLite.
So, when you try to insert the rows from old_cities to cities you get an error because 'pan' is not allowed in the column id as it is defined now.

Placeholder while retrieving data from table

I have a table that contains common subjects text, that requires insertion of some string at run time. For example below:
CREATE TABLE certification.cert_email_dtls (
cert_eid_id numeric(10,0),
cert_eid_email_body character varying(8000),
);
insert into certification.cert_email_dtls(1,'hello world <blank-value1>);
insert into certification.cert_email_dtls(2,'hello guys <blank-other-value2>);
insert into certification.cert_email_dtls(3,'hello <blank-value3> india <some-other-value4>);
and so on. <some-value>,<some-other-value> etc come at run time.
SELECT cert_eid_id ,
cert_eid_email_body,
INTO v_id,
v_email_body_end
FROM certification.cert_email_dtls where cert_eid_id = in_id;
My requirement is to insert that some-values that are coming in between and generate the final email body.
format() might be the perfect tool for this. Read details in the manual.
If you can save cert_eid_email_body in a compatible format, like:
CREATE TABLE cert_email_dtls (
cert_eid_id serial PRIMARY KEY
, cert_eid_email_body text
);
INSERT INTO cert_email_dtls (cert_eid_email_body)
VALUES ('hello %1$s india %2$s');
The whole operation can be as simple as:
SELECT format(cert_eid_email_body, 'foo', 'bar', 'baz') AS cert_eid_email_body
FROM cert_email_dtls
WHERE cert_eid_id = 1;
Result:
cert_eid_email_body
-------------------
hello foo india bar
Note that the 3rd parameter 'baz' is silently ignored, since it is not referenced in the string.
SQL Fiddle.
Aside: Don't use numeric(10,0) for an ID or primary key. integer or bigint typically serve you better. Using serial PRIMARY KEY above as it probably should be.

Learn SQL The Hard Way - Exercise 2 - Creating Multitable DB - .schema command

I understand the sql in this exercise perfectly, but the setup type tasks are confusing to me. Zed asks you to use the following SQL to create the following tables in a new database that are related by the id key. I'm fine there.
CREATE TABLE person (
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT,
age INTEGER
);
CREATE TABLE pet (
id INTEGER PRIMARY KEY,
name TEXT,
breed TEXT,
age INTEGER,
dead INTEGER
);
CREATE TABLE person_pet (
person_id INTEGER,
pet_id INTEGER
);
In my windows command prompt I entered:
C:\SQLite> sqlite3 ex2.db < ex2.sql
ex2.db is my new db and ex2.sql contains the create statements listed above.
Zed then asks you to enter .schema using the sqlite command prompt. Nothing happens for me. It does not dump. Does .schema only work with Linux or OSX? I'm on windows.
The following is what he says you should get:
sqlite> .schema
CREATE TABLE person (
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT,
age INTEGER
);
CREATE TABLE person_pet (
person_id INTEGER,
pet_id INTEGER
);
CREATE TABLE pet (
id INTEGER PRIMARY KEY,
name TEXT,
breed TEXT,
age INTEGER,
dead INTEGER
);
sqlite>
Instead, this is what I get:
sqlite> .schema
sqlite>
You have to start the sqlite3 tool with:
C:\SQLite> sqlite3 ex2.sb
sqlite> .schema
...
Without a database file name, sqlite3 just creates a temporary database.
In the Windows command prompt type:
C:\SQLite> sqlite3 ex3.db
sqlite will open.
sqlite> .schema
Create statements will display.

Getting "syntax error, unexpected tIDENTIFIER..." when trying to insert rows into SQLite via Ruby

Anyone have any ideas? I get this error message in bash...
insert_code_sam.rb:31: syntax error, unexpected tIDENTIFIER, expecting ')'
"INSERT INTO index1 (name) VALUES ("test1");"
^
insert_code_sam.rb:32: syntax error, unexpected ')', expecting end-of-input
In a single file insert_code_sam.rb, I'm trying to create a new db, create two tables, and insert a test row. The SQlite table gets created without a problem, but I can't seem to insert rows.
require "sqlite3"
db = SQLite3::Database.new( "new_database.db" )
db.execute(
"CREATE TABLE index1 (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
tagline TEXT,
blurb TEXT,
photo_url TEXT);"
)
db.execute(
"CREATE TABLE student_profile (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name_id INTEGER,
thumbnail_url TEXT,
background_url TEXT,
quote TEXT,
bio TEXT,
education TEXT,
work TEXT,
github TEXT,
treehouse TEXT,
codeschool TEXT,
coderwall TEXT);"
)
db.execute(
"INSERT INTO index1 (name) VALUES ("test1");"
)
db.execute(
"INSERT INTO index1 (name) VALUES ('test1');"
)
Alternative way if you wanted to use "" delimiter:
db.execute(
"INSERT INTO index1 (name) VALUES (\"test1\");"
)
You are prematurely ending the string – your code is not valid Ruby syntax. SQLite expects single quoted strings, anyway. The solution is to use single quotes for the VALUES:
db.execute(
"INSERT INTO index1 (name) VALUES ('test1');"
)

REPLACE INTO sqlite doesn't replace

got a weird problem. I have a sqlite table in my objective-c app:
NSString *sql = #"CREATE TABLE IF NOT EXISTS user_results (id INTEGER PRIMARY KEY ASC AUTOINCREMENT, gameID INTEGER UNIQUE, gameDesc TEXT, result INTEGER)";
Then I execute query:
[[DatabaseController getInstance].resultsDB executeUpdate:#"REPLACE INTO user_results (gameID, gameDesc, result) VALUES (?, ?, ?)",[NSNumber numberWithInt:self.gameID],[test JSONRepresentation],[NSNumber numberWithInt:sumBalls]];
But the problem is that it doesn't replace the row with the same gameID, it just adds one (even though it's UNIQUE), any ideas why would it happen?
P.S. I'm using FMDB to work with sqlite.
Thanks in advance.
Solution: Had to use [NSNumber numberWithInt:self.gameID].integerValue instead of [NSNumber numberWithInt:self.gameID] when sending to sql query.
Has your schema changed, with the UNIQUE constraint added later? Your schema & SQL should work as expected. I just tried this and it works fine:
sqlite3
CREATE TABLE IF NOT EXISTS user_results (id INTEGER PRIMARY KEY ASC AUTOINCREMENT, gameID INTEGER UNIQUE, gameDesc TEXT, result INTEGER);
insert into user_results values (1,1,'hi', 1); --insert 2 test rows
insert into user_results values (2,2,'2', 2);
select * from user_results;
1|1|hi|1
2|2|2|2
Now an insert fails:
insert into user_results values (3,1,'1', 1);
Error: column gameID is not unique
REPLACE INTO does what you expect:
replace into user_results (gameid, result) values (2, 3);
select * from user_results;
1|1|hi|1
3|2||3
It deleted the row with id 2, and replaced it with a new row id 3 and gameid 2. Unless you were expecting it to replace the primary key=2 row? What Sqlite does is delete any prior rows that would cause violation of the unique key, then inserts a new row. See http://www.sqlite.org/lang_conflict.html. Note it didn't add an EXTRA row. It deleted one and added one (in other words, 'replaced' :)
If your replace into SQL included the id column, that would work, here I'm effectively updating the row with id 3. Of course you'd have to figure out the id of the row you wanted to replace...
replace into user_results values (3,3,'2', 2);
select * from user_results;
1|1|hi|1
3|3|2|2
Is the id column something you really care about? Sqlite will create such a column for you anyway.
The gameID field is not the PRIMARY KEY, ID is. As you have it, the REPLACE INTO will only work with the ID field. I recommend making the gameID field the primary key to get the result that you are looking for.
NSString *sql = #"CREATE TABLE IF NOT EXISTS user_results (gameID INTEGER PRIMARY KEY, gameDesc TEXT, result INTEGER)";