Calling prepare with mysqli - SQL syntax error - mysqli

$q2 = "UPDATE `tasks` SET `title` = ?, task = ?, rules = ?, media = ?, type = ?, xp = ?, available = ?, timestamp = ? WHERE id = ?";
if ($stmt = $mysqli->prepare($q2)) {
$stmt->bind_param("sssssissi", $_POST["tasktitle"], $_POST["editor"], $_POST["rules"], serialize($_POST["media"]), $_POST["type"], $_POST["xp"], $a = 0, strtotime("now"), $_GET['id']);
$stmt->execute();
$stmt->close();
}
$r = $mysqli->query($q2) or die($mysqli->error);
I got this error msg:
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 '?, task = ?, rules = ?, media = ?, type = ?, xp = ?, available = ?, timestamp = ' at line 1
What is problem, and how can i solve it?

I'm pretty certain it's coming from the call to $mysqli->query() which needs a properly escaped query (ie, none of that nice safe parameter stuff). That explains why it's complaining at the first ?.
Quick way to check is to actually comment out the entire if statement and se if the error still appears. If so, you know it's the query rather than the prepared statement execution.
My question to you is: why are you executing the prepared statement and then trying to run it again as a query?
I think you'll find the execute does your update quite well enough. Get rid of the call to query and you should be fine.

Related

having syntax error trying to use on duplicate

sql_insert_query = "insert into TABLE1 (building, course, description, course_type, course_type_desc, dual_credit)
VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE building = VALUES(building), course = VALUES(course), description = VALUES(description), course_type = VALUES(course_type), course_type_desc = VALUES(course_type_desc), dual_credit = VALUES(dual_credit);"
cursor.executemany(sql_insert_query, listCourse)
pyodbc.ProgrammingError: ('42000', u"[42000] [Microsoft][SQL Server
Native Client 11.0][SQL Server]Incorrect syntax near the keyword 'ON'.
(156) (SQLExecDirectW); [42000] [Microsoft][SQL Server Native Client
11.0][SQL Server]Statement(s) could not be prepared. (8180)")
This one below only works, but adds duplicate when running again.
"insert into TABLE1 (building, course, description, course_type, course_type_desc, dual_credit) VALUES (?, ?, ?, ?, ?, ?)"
I tied '%s' this did not work so I am using '?'
I have resolved it by tile with tuple
listCourse = numpy.tile(courses, 2)
listCourse = map(tuple,numpy.tile(courses, 2))

What is best way to call PostgreSQL function from CodeIgniter

I am using CodeIgniter 3.0.6 and PostgreSQL 9.4. I have a PostgreSQL function with some 4 parameters, out of 4 parameters 3 are string and one is of type bit. I have used the following method to call my function
$query = "SELECT * FROM my_function('$param1', '$param2', '$param_bit', '$param4')";
return $this->db->query($query);
the above method works fine for me, but for security reasons I have decided to use query binding so the values are automatically escaped. I tried the following method
$query = "SELECT * FROM my_function(?, ?, ?, ?)";
return $this->db->query($query, $param1, $param2, $param_bit, $param4);
but is shows
ERROR: syntax error at or near "," LINE 1
So I tries a different methods,
$query = "SELECT * FROM my_function('?', '?', '?', '?')";
return $this->db->query($query, $param1, $param2, $param_bit, $param4);
but it shows No function matches the given name and argument types. You might need to add explicit type casts.
$query = "SELECT * FROM my_function(?::varchar, ?::varchar, ?::bit, ?::varchar)";
return $this->db->query($query, $param1, $param2, $param_bit, $param4);
but it shows ERROR: syntax error at or near "::" LINE 1:
Even tried with quotes and datatypes, but none of them worked for me.
If anyone ever worked before with PostgreSQL functions with parameters, please share how it can be done.
Any help would be appreciated, thanks in advance.

PostgreSQL, Perl, DBD and the Insert command with "TO_TIMESTAMP"

I'm programming a script which queries some devices and writes the data to a PostgreSQL database.
The data includes a date which is formatted like 31.12.2015 13:45:00. The database uses the DateType "German" and the column is of the type Timestamp without timezone.
I always get this error message
DBD::Pg::st execute failed: ERROR: invalid input syntax for type timestamp:
"TO_TIMESTAMP('19.06.2015 11:24:20','DD.MM.YYYY HH24:MI:SS')::timestamp without time zone"
at temp_alcp2e_db.pl line 80, line 289.
I'm using this code, where $date_db has the date value:
$date_db = 'TO_TIMESTAMP(\'' . $date_db . '\',\'DD.MM.YYYY HH24:MI:SS\')::timestamp without time zone';
$stmt = $dbh->prepare("INSERT INTO rifutemp (\"USER_LINK_ID\", \"IP\", \"DATUM\", \"TEMPERATURE\") VALUES (?, ?, ?, ?)");
$stmt->execute($key_bgtr, $key_ip, $date_db, $temperatur) or die $DBI::errstr;
Hopefully, someone can show me what I did wrong.
The function can (and must) be part of the prepared statement.
Re-write your code as follows:
$stmt =$dbh->prepare(q{
INSERT INTO rifutemp ("USER_LINK_ID","IP","DATUM","TEMPERATURE")
VALUES (?, ?,
TO_TIMESTAMP(?, 'DD.MM.YYYY HH24:MI:SS')::timestamp without time zone,
?)
});
$stmt->execute($key_bgtr,$key_ip,$date_db,$temperatur) or die $DBI::errstr;
Ok, I've found my problem / the source of the errors:
To manage the Database visually I'm using the "EMS SQL Manager Lite for PostgreSQL", and this nice GUI tool always sets the DateStyle options to "ISO, MDY".
I've just changed my code like this:
$dbh->do("SET datestyle = 'German'");
$stmt =$dbh->prepare("INSERT INTO rifutemp (\"USER_LINK_ID\",\"IP\",\"DATUM\",\"TEMPERATURE\")
VALUES (?, ?, ?, ?)");
$stmt->execute($key_bgtr,$key_ip,$date_db,$temperatur) or die $DBI::errstr;
and set the $date_db variable to the correct format:
$date_db = Time::Piece->new->strftime('%d.%m.%Y %H:%M:%S');
and now everything works fine!

perl DBI and placeholders

I have this query select * from table where ID in (1,2,3,5...)
How is it possible to build this query with the DBI using placeholders ?
for example :
my #list = (1, 2, 3, 4, 5);
my $sql = "select * from table where ID in (?)";
$sth->prepare($sql);
$sth->execute();
What argument should I send to execute? Is it a list or a string separated by , or something else?
This should build your query dynamically according to the number of items in your array
my #list =(1,2,3,4,5);
my $sql ="select * from table where ID in (#{[join',', ('?') x #list]})";
It's not possible in that way. You need to specify a placeholder for each item in your array:
my #list = (1,2,3,4,5);
my $sql = "select * from table where ID in (?,?,?,?,?)";
$sth->prepare($sql);
$sth->execute(#list);
If your #list is not a fixed size, you need to build the $sql with the proper number of placeholders.
Quoting DBI documentation:
Also, placeholders can only represent single scalar values. For example, the following statement won't work as expected
for more than one value:
SELECT name, age FROM people WHERE name IN (?) # wrong
SELECT name, age FROM people WHERE name IN (?,?) # two names
Rewrite to:
my $sql = 'select * from table where ID in ( ?, ?, ?, ?, ? )';
$sth->prepare($sql);
$sth->execute(#list);
If you are using DBI to access a PostgreSQL database with the DBD::Pg driver, you can use:
my #list = (1, 2, 3, 4, 5);
my $sql = "select * from table where ID = ANY(?::INT[]);";
$sth->prepare ($sql);
$sth->execute (\#list);
Unless you know the exact number of elements you cannot use placeholders. Try this:
my #list = (1, 2, 3, 4, 5); # any number of elements
my $in = join(',', map { $dbh->quote($_) } #list);
my $sql = "select * from table where someid IN ($in)";
If you switch to DBIx::Simple you can just say:
$db->query('INSERT INTO foo VALUES (??)', $foo, $bar, $baz);
?? Means "as many as needed"
Edit:
Actually, I was a little too optimistic: "If the string (??) is present in the query, it is replaced with a list of as many question marks as #values."
So this does not seem to work:
$db->query( "SELECT * FROM foo WHERE id IN (??) AND stuff=?", #ids, $stuff )
Still useful though..
For the curious, the code in the module is:
# Replace (??) with (?, ?, ?, ...)
sub _replace_omniholder {
my ($self, $query, $binds) = #_;
return if $$query !~ /\(\?\?\)/;
my $omniholders = 0;
my $q = $self->{dbd} =~ /mysql/ ? $quoted_mysql : $quoted;
$$query =~ s[($q|\(\?\?\))] {
$1 eq '(??)'
? do {
Carp::croak('There can be only one omniholder')
if $omniholders++;
'(' . join(', ', ('?') x #$binds) . ')'
}
: $1
}eg;
}
I found a sure way for this to work summarizing all of the above advice. My Production query (I posted a much simpler version here) uses IN <>, where neither the codes nor their quantity is unknown. It could be a single Code (e.g. FIN), or a series of them (FITLC FITLD FITLU FITSC FITSD FITSU MDYLC MDYLD MDYLU). Some function returns that as a list.
The code that makes this happen is
#codes = get_muni_evcode( $category );
my $in = join( ', ', ('?') x #codes );
print "\n\nProcessing Category: $category --> Codes: #codes .. in: $in\n";
my $sql = "select distinct cusip9
from material_event
where event_date between (trunc(sysdate) - 1) + 2/3 and trunc(sysdate) + 2/3
and event_code in ($in)";
my $sth2 = $dbh->prepare($sql);
$sth2->execute( #codes );
while (my $s2 = $sth2->fetchrow_hashref('NAME_lc'))
{
my $cusip9 = $s2->{cusip9};
print "$cusip9\t";
.................. further processing ..............
}
The result sample:
Processing Category: RatingChange --> Codes: FITLC FITLD FITLU FITSC FITSD FITSU MDYLC MDYLD MDYLU MDYSC MDYSD MDYSU SPLD SPLPR SPLU SPSD SPSPR SPSU .. in: ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
359496HQ2 359496GB6 359496GH3 359496GL4 359496HU3 359496HS8 359496HA7 359496HF6 359496GM2 359496HM1 359496HR0 359496HT6 359496GY6 359496GJ9 359496HL3 359496GU4 359496HK5 359496HN9 359496HP4 359496GW0 359496GZ3 359496HC3 359496GC4 359496GK6 359496GP5 359496GV2 359496GX8 359496GN0
I'm extremely grateful to everybody who posted their ideas here that finally made me find the right way to do this. It must be a pretty common problem I think.

Debugging sqlite

Is there a way to see what the resulting 'showStatement' is after sqlite3_prepare_v2 and sqlite3_bind_xxx ?
Running this query :
SELECT *
FROM shows, locations
WHERE (shows.day_id = 1)
AND (shows.id IN (6,7,15,19,23,66))
AND (shows.location_id = locations.id)
ORDER by locations.sort_order
runs perfectly in SQLite Manager and in code when I enter it EXACTLY like that. If I however do parameter substitution the query returns no results...
if (sqlite3_open([databasePath UTF8String],&showsDatabase) == SQLITE_OK){
const char *sqlStatement = "SELECT * FROM shows, locations WHERE (shows.day_id = ?) AND (shows.id IN (?)) AND (shows.location_id = locations.id) ORDER by locations.sort_order";
sqlite3_stmt *showStatement;
if(sqlite3_prepare_v2(showsDatabase, sqlStatement, -1, &showStatement, NULL) == SQLITE_OK) {
sqlite3_bind_int(showStatement, 1, forDay);
sqlite3_bind_text(showStatement, 2, allFavorites,-1,NULL);
int error = sqlite3_step(showStatement);
while(sqlite3_step(showStatement) == SQLITE_ROW) {
...
The problem must lie in the IN (6,7...) part, without that it works perfect.
My debugger shows me that forDay = 1 and that allFavorites = 6,7,15,19,23,66
but the error = 101 = sqlite3_step() has finished executing = no lines found
Being able to see the 'showStatement' variable in one way or another would solve the problem, however the debugger doesn't give that info
You can't bind IN (?) with an array.
You need to write shows.id IN (?, ?, ?, ?, ?, ?) and bind each parameter separately. The number of question marks also has to match the number of parameters so you might need to construct the query dynamically if the number can vary.