sqlite3_stmt *stmt;
sqlite3_prepare_v2(db, "INSERT INTO links(NAME, LINK, SIZE, STARRED) VALUES ('?' , '?', ? , 0);", 41, &stmt, NULL);
if(stmt != NULL) {
sqlite3_bind_text(stmt, 1, name, 0, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, link, 0, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3, size);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}else{
printf("%sError during insertion in the database%s\n", RED, RST);
}
sqlite3_close(db);
I always get on the output Error during insertion in the database but can't understand why, maybe something related to sqlite3_prepare_v2 but doesn't know what, I tried to execute the query 'manually' with random data and it works.
The size of the zSql statement is 69 characters. It is is better to us -1 for length as by default it will be null-terminated string and size is automatically computed :
sqlite3_prepare_v2(db, "INSERT INTO links(NAME, LINK, SIZE, STARRED) VALUES (?, ?, ? , 0);", -1, &stmt, NULL);
Do not forget the 3rd '?' in the statement for the 3rd argument.
Edit : write it as ? in the statement
You bind twice item 2 of the statement and ? is missing for item 3.
Just solved by changing the third parameter of sqlite3_prepare_v2() that is the maximum length of zSql in bytes, and 47 is to small.
Related
My code is like this...
char dis[20];
int tc,tac,trc;
puts("Enter the data:\n");
puts("District : ");
while((getchar())!='\n');
fgets(dis,20,stdin);
puts("Total Cases : ");
scanf("%d",&tc);
puts("Total Active Cases : ");
scanf("%d",&tac);
puts("Total Recovered Cases : ");
scanf("%d",&trc);
sql = "INSERT INTO COV VALUES (dis,tc,tac,trc);"; //won't work
sql = "INSERT INTO COV VALUES ('abc',1,1,0);"; //works
database = sqlite3_exec(db, sql,0,0,0);
I want to save the values obtained from user in sqlite database but I can't do it as shown below.
It works if I just pass the exact value (i.e. during compile time).
How can I send values computed during runtime execution to sqlite database?
Have a look to the Sqlite C interface documentation.
Assuming you have a table defined like this:
CREATE TABLE COV (id PRIMARY KEY, dis VARCHAR, tc INTEGER, tac INTEGER, trc INTEGER);
You need to bind your parameters with specific bind API to prevent SQL injection.
Prepare your INSERT string using ?N template:
char sql[512];
snprintf(sql, sizeof(sql), "INSERT INTO COV(dis, tc, tac, trc) VALUES (?1,?2,?3,?4);");
Then bind your program variables with the corresponding parameter:
sqlite3_stmt *stmt;
sqlite3_prepare_v2(db, sql, sizeof(sql), &stmt, NULL);
sqlite3_bind_text(stmt, 1, dis, 20, NULL);
sqlite3_bind_int(stmt, 2, tc);
sqlite3_bind_int(stmt, 3, tac);
sqlite3_bind_int(stmt, 4, trc);
ret = sqlite3_step(stmt);
if (ret == SQLITE_DONE)
printf("record inserted!\n");
else
printf("Error: %s\n", sqlite3_errmsg(db));
sqlite3_finalize(stmt);
You need to put the actual values in using sprintf
char sqlscript[128];
Then, since you are using sql to send to the DB, assign sqlscript to sql first
sql = sqlscript;
sprintf(sql, "INSERT INTO COV VALUES('%s', %d, %d, %d);", dis, tc, tac, trc);
So I'm working with sqlite and I created this database:
sql = "CREATE TABLE COMPANY(" \
"NAME TEXT PRIMARY KEY NOT NULL," \
"LAST TEXT," \
"PIN INT," \
"DL INT,"\
"SSN INT,"\
"EMAIL TEXT,"\
"BALANCE REAL );";
I'm trying to insert a value in NAME but it keeps giving the the error "no such column: John
This is how I try to insert it: (assume everything is declared)
strcpy(text, "John");
sprintf (sql,"INSERT INTO ATM (NAME,PIN) VALUES (%s',%d);",text,number);
When I use this line of code instead:
sprintf (sql,"INSERT INTO ATM (NAME,PIN) VALUES ('john',%d);",number);
It worked and I was able to insert these two values.
why isn't the first one working?? Please someone help
Thank you
As I would prefer you would use prepared statement, I will replicate your code with prepared statement.
sqlite3_stmt *stmt;
sqlite3_prepare_v2(db, "INSERT INTO ATM (NAME,PIN) VALUES (?,?);", 41, &stmt, NULL);
if(stmt != NULL) {
sqlite3_bind_text(stmt, 1, "John", SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 2, number);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
Using sprintf to create your statement is insecure and error prone , you should learn about SQL Injection
You forgot to put a ' before %s. This would be the correct sentence
sprintf (sql,"INSERT INTO ATM (NAME,PIN) VALUES ('%s',%d);",text,number);
Hope this helps
You're missing the beginning ' in your first code snippet. That means, it will give you something like:
INSERT INTO ATM (NAME,PIN) VALUES (John',42);
which is probably why it's treating the unquoted John as a column name rather than a string.
The statement should be:
sprintf (sql,"INSERT INTO ATM (NAME,PIN) VALUES ('%s',%d);",text,number);
Two other things. Unless you're certain about the provenance of your variables, blindly injecting them into SQL statements is a bad idea, and opens you up to SQL injection attacks.
Secondly, C is mostly a free-format language, you don't need those \ character at the ends of the lines in your first code block.
I am trying to insert the values from my text file to a record using app engine.
I know this could be done using file layout but my requirement suggests not to use file layout but needs to insert into record using app engine people code.
I am writing the following PeopleCode in my appengine
(here i am trying to add only one field value to my record in this example)
Local File &MYFILE;
Local Record &REC_ERN;
&MYFILE = GetFile("c:\sample.csv", "R", %FilePath_Absolute);
If &MYFILE.IsOpen Then
While &MYFILE.ReadLine(&STRING);
MessageBox(0, "", 0, 0, &STRING);
&source_type_id = Substring(&STRING, 1, 3);
&Stmt= "INSERT INTO KGS_TEST (ID) VALUES ( &source_type_id)";
SQLExec(&Stmt);
REM MessageBox(0, "", 0, 0, &source_type_id);
End-While;
End-If;
&MYFILE.Close();
The problem I am facing is &source_type_id = Substring(&STRING, 1, 3);
the variable &source_type_id has the value but i need to insert this into a record which I have created which has fields (ID,NAME,AGE,department).
The issue you are having is that your variable &source_type_id is inside a string and therefore is interpreted literally as part of the string instead of the value of the variable as you want.
What you need to do is put a bind variable in the string for the value and then pass the value as a parameter to SqlExec.
Local File &MYFILE;
&MYFILE = GetFile("c:\sample.csv", "R", %FilePath_Absolute);
If &MYFILE.IsOpen Then
While &MYFILE.ReadLine(&STRING);
MessageBox(0, "", 0, 0, &STRING);
&source_type_id = Substring(&STRING, 1, 3);
&Stmt= "INSERT INTO KGS_TEST (ID) VALUES ( :1)";
SQLExec(&Stmt,&source_type_id);
REM MessageBox(0, "", 0, 0, &source_type_id);
End-While;
End-If;
&MYFILE.Close();
In my previous implementation, I was streaming results from a sqlite3 table directly into my output application. However, since I am changing the interface to a temporary data structure, I now need to get the number of rows. The preferred way to do that seems to be with a temporary table, so my original
sprintf(query,"SELECT %s AS x, AVG(%s) AS y, AVG((%s)*(%s)) AS ysq FROM %s WHERE %s=%s AND %s GROUP BY x;",x,y,y,y,from,across,val,where);
sqlite3_prepare_v2(db, query, -1, &acResult,NULL);
while(sqlite3_step(acResult)==SQLITE_ROW) { ... }
sqlite3_finalize(acResult);
turns into
sprintf(query,"CREATE TEMP TABLE tt AS SELECT %s AS x, AVG(%s) AS y, AVG((%s)*(%s)) AS ysq FROM %s WHERE %s=%s AND %s GROUP BY x;",x,y,y,y,from,across,val,where);
sqlite3_prepare_v2(db, query, -1, &acResult,NULL);
sqlite3_step(acResult);
sqlite3_finalize(acResult);
sqlite3_prepare_v2(db, "SELECT COUNT(*) FROM tt;", -1, &acResult, NULL);
sqlite3_step(acResult);
int length = sqlite3_column_int(acResult,0);
sqlite3_finalize(acResult);
sqlite3_prepare_v2(db, "SELECT x,y, ysq FROM tt;", -1, &acResult, NULL);
while(sqlite3_step(acResult)==SQLITE_ROW) { ... }
sqlite3_finalize(acResult);
sqlite3_prepare_v2(db, "DROP TABLE tt;", -1, &acResult, NULL);
sqlite3_step(acResult);
sqlite3_finalize(acResult);
Now, this mostly works. The problem is that I have this inside a loop across another stepping query, which seems to be responsible for the table being locked when I try to drop it. If I finalize that query, it "works" (the drop works; everything else breaks because it's part of the logic). There is no possible way the outer query could be referencing tt, because I created it within that "scope".
Is there a way of reminding sqlite that it shouldn't be locked, or am I stuck switching the outer loop away from streaming as well?
This is a read-only application (with the exception of the temp table), if that helps.
I would like to create/update text columns in sqlite3.
When i retrieve rows after the create/update, the text is '?'.
Integer values are properly persisted however.
My text statements look like this:
const char *sql = "INSERT INTO todo(title, description, priority, status, created, expires, posx, posy, updated)"
" VALUES('?', '?', '?', '?', '?', '?', '?', '?', '?');";
if (sqlite3_prepare_v2(database, sql, -1, &insert_statment, NULL) != SQLITE_OK)
...
sqlite3_bind_text(update_statment, 5, [[dt stringFromDate:self.updated] UTF8String], -1, SQLITE_TRANSIENT);
I've tried SQLITE_TRANSIENT as well as SQLITE_STATIC. Both cases seem to yield same results ('?'). I have also verified that the text values are valid when they are passed into the appropriate sql statements here.
Any ideas?
Remove the ' characters around ? in your sql string.
SQLITE_TRANSIENT tells SQLite to copy your string. Use this when your string('s buffer) is going to go away before the query is executed.
SQLITE_STATIC tells SQLite that you promise that the pointer you pass to the string will be valid until after the query is executed. Use this when your buffer is, um, static, or at least has dynamic scope that exceeds that of the binding.