Zend_Db_Statement_Pdo->execute with expression in params - php

I try to execute insert statement with "on duplicate" part. As I know Zend doesn`t support this, so I use simple statement:
$sql = "INSERT INTO agent(`inn`, `name`, `created`) VALUES(:inn, :name, :created) ON
DUPLICATE KEY UPDATE `inn` = :inn, `name` = :name, `created` = :created";
$stmt = $this->db->prepare($sql);
$stmt->execute($bind);
Where $bind - is array:
array(
'inn'=>1234567890,
'name'=>'test user',
'created' = new Zend_Db_Expr('NOW()')
);
If I try this query through phpMyAdmin - all works fine,
but after script execution the "created" column value is '0000-00-00 00:00:00'.
WTF?

You can't use an expression as an argument to a placeholder in a prepared statement. It will be interpreted as a string. This has nothing to do with zend framework.
You can either created a formatted date string in php and use that, or use now() in the prepared statement like
VALUES(:inn, :name, NOW())
Another solution, if you need to sometimes supply a datetime, and sometimes use NOW(), is using conditionals to check for that specific case
VALUES(:inn, :name, IF(:created = 'NOW()', NOW(), :created))

Related

what is the date format to insert a date using sqlsrv_query?

I get all rows by this sql query:
$sql = "SELECT * FROM USERS";
$stmt3 = sqlsrv_query( $conn, $sql3 , $params, $options );
But when I want to insert:
$sql2 =
"INSERT INTO USER (USER_ID, USER_NOM, USER_DATE)
VALUES (".$row['USER_ID'].", '".$row['USER_NOM']."','".$row['USER_DATE']->format('Y-m-d h:i:s.v')."')";
I get this error:
Converting the varchar data type to datetime produced an out of range
value.
This is my $sql2:
INSERT INTO USER (USER_ID, USER_NOM, USER_DATE) VALUES (1,DANI,'2020-07-22 12:00:00.000')
You need to consider the following:
You need to use parameterized statements to prevent possible SQL injection issues. As is mentioned in the documentation, the sqlsrv_query() function is well-suited for one-time queries and should be the default choice to execute queries unless special circumstances apply. This function provides a streamlined method to execute a query with a minimum amount of code. The sqlsrv_query function does both statement preparation and statement execution, and can be used to execute parameterized queries.
By default smalldatetime, datetime, date, time, datetime2, and datetimeoffset types will be returned as PHP DateTime objects, but this behaviour can be changed by setting the 'ReturnDatesAsStrings' option in the connection string or at the statement level (more explanations can be found here).
You have two options, if you are sure, that date/time values are returned as PHP DateTime objects:
Pass datetime values as text using unambiguous format (e.g. 2020-07-22T12:00:00.000)
Pass datetime values as PHP DateTime objects using extended syntax for parameters for the sqlsrv_query() call.
Example (datetime values are passed as text):
<?php
// SELECT statement
$sql3 = "SELECT * FROM USERS";
$stmt3 = sqlsrv_query($conn, $sql3 , $params, $options);
if ($stmt3 === false) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
// INSERT statements
while ($row = sqlsrv_fetch_array($stmt3, SQLSRV_FETCH_ASSOC)) {
$sql2 = "
INSERT INTO USER (USER_ID, USER_NOM, USER_DATE)
VALUES (?, ?, ?)
";
$params = array(
$row['USER_ID'],
$row['USER_NOM'],
$row['USER_DATE']->format('Y-m-d\TH:i:s.v'));
);
$stmt2 = sqlsrv_query($conn, $sql2 , $params);
}
?>
Example (datetime values are passed as PHP DateTime objects):
<?php
// SELECT statement
$sql3 = "SELECT * FROM USERS";
$stmt3 = sqlsrv_query($conn, $sql3 , $params, $options);
if ($stmt3 === false) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
// INSERT statements
while ($row = sqlsrv_fetch_array($stmt3, SQLSRV_FETCH_ASSOC)) {
$sql2 = "
INSERT INTO USER (USER_ID, USER_NOM, USER_DATE)
VALUES (?, ?, ?)
";
$params = array(
array($row['USER_ID'], SQLSRV_PARAM_IN),
array($row['USER_NOM'], SQLSRV_PARAM_IN),
array($row['USER_DATE'], SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_DATETIME, SQLSRV_SQLTYPE_DATETIME)
);
$stmt2 = sqlsrv_query($conn, $sql2 , $params);
}
?>
The Datetimevalue to be inserted in Datetime type , it should be in 'YYYY-MM-DD HH:MM:SS' format.
The supported range is '1000-01-01 00:00:00' to '9999-12-31 23:59:59'.
Note:- For More Details Please refer this https://dev.mysql.com/doc/refman/8.0/en/datetime.html

Set a default value for INSERT statement PHP

I know this should be a simple question, i have the following insert statement which is inserting values captured via a form, all works well but i would also like to add a default value to a column not on my form(lets say language for example), i don't want to add the default value via the database, as i have two forms that are coming together to the one table.
$stmt = DB::query(Database::INSERT,
'INSERT INTO `my_products` (`first_name`, `initial`, `last_name`, `street`)
VALUES (:first_name, :initial, :last_name, :street)');
$stmt->param(':first_name', $post['first_name']);
$stmt->param(':initial', $post['initial']);
$stmt->param(':last_name', $post['last_name']);
$stmt->param(':street', $post['street']);
Is there a way to specify a default value via the above?
What's wrong with this?
$stmt = DB::query(Database::INSERT,
"INSERT INTO `my_products` (`first_name`, `initial`, `last_name`, `street`, `myColumn`)
VALUES (:first_name, :initial, :last_name, :street, 'my default value')");
Or possibly:
$stmt = DB::query(Database::INSERT,
'INSERT INTO `my_products` (`first_name`, `initial`, `last_name`, `street`, `myColumn`)
VALUES (:first_name, :initial, :last_name, :street, :my_column)');
...
$stmt->param(':my_column', 'my default value');
You could use my tiny library ValueResolver in this case, for example:
$stmt->param(':my_column', ValueResolver::resolve($post['first_name'], 'default')); // returns 'default' if $post['first_name'] is empty
and don't forget to use namespace use LapaLabs\ValueResolver\Resolver\ValueResolver;
There are also ability to typecasting, for example if your variable's value should be integer, so use this:
$id = ValueResolver::toInteger('6 apples', 1); // returns 6
$id = ValueResolver::toInteger('There are no apples', 1); // returns 1 (used default value)
Check the docs for more examples

Wrong SQL Syntax? [duplicate]

This question already has answers here:
MySQL, safely using reserved word in query [duplicate]
(2 answers)
Closed 9 years ago.
I am building a small Twitter clone for personal use, and I have so trouble with it.
Fist, I want to show you my SQL structure of the table "poke_history":
http://puu.sh/3Sci0.png
This is the command I use to insert the values into a table (in PHP):
$insert = "INSERT INTO poke_history (id, from, time, reason) VALUES ('".$to_id."', '".$from_id."', '".$time."', '".$reason."')";
mysql_query($insert) or die(mysql_error());
This is the annoying error that I am getting:
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 'from, time, reason) VALUES ( '1'' at line 3.
Let me clarify some things.
$to_id is a number.
$from_id is a number.
$time is a number (coming from PHP's time()).
$reason is a text string.
I am using MySQL and PHP5.
Try to quote your column identifiers like
INSERT INTO poke_history (`id`, `from`, `time`, `reason`) ...
Everything inside `` is considered to be a "identifier" not a language keyword. From the SQL-syntax it should be clear that after INSERT INTO tablename cannot come a FROM, but the MySQL sometimes needs this kind of guidance (and other sql parsers, too).
credit to mario as well:
from is a reserved keyword. Use backticks to escape them.
for example
`from`
INSERT INTO table (`from`) ....
So your code would like this:
$insert = "INSERT INTO poke_history (`id`, `from`, `time`, `reason`) VALUES ('".$to_id."', '".$from_id."', '".$time."', '".$reason."')";
mysql_query($insert) or die(mysql_error());
$insert = "INSERT INTO poke_history (`id`, `from`, `time`, `reason`) VALUES (".$to_id.", ".$from_id.", ".$time.", '".$reason."')";
mysql_query($insert) or die(mysql_error());
Numbers don't need to be quoted. Only strings.
Also don't use mysql, it's deprecated. Better use PDO, with prepared statements, to avoid issues like this.
You should try to use prepared statements to prevent SQL injection.
$query = "
INSERT INTO
poke_history (`id`, `from`, `time`, `reason`)
VALUES
(:id, :from, :time, :reason)";
$db = new PDO("mssql:host=sqlserver;dbname=database", "username", "password");
$statement = $db->prepare($query);
$parameters = array(
":id" => $name,
":from" => $from,
":time" => $time,
":reason" => $reason
);
$statement->execute($parameters);
I think that you forgot to add * in between INSERT and INTO, here is the fixed script:
$insert = "INSERT * INTO poke_history (id, from, time, reason) VALUES ('".$to_id."', '".$from_id."', '".$time."', '".$reason."')";
mysql_query($insert) or die(mysql_error());
The reason why you are getting the error is because you are trying to use a built in function name for one of your columns. Say you have the following CREATE TABLE...
CREATE TABLE customers
(
name varchar(80),
streetAddr varchar(160),
"from" varchar(60),
);
Notice that to create the table I had to put the column from in quotes. Now if you wanted to insert a row into this table, your insert statement should look like the following:
INSERT INTO ShoppingFun.dbo.customers
(
name,
streetAddr,
"from"
)
VALUES
(
'MRBubbleGum',
'1061 SW BubbleGumVillage St',
'yourmom'
)

Php blocking on variable declaration (w/psql)

I'm kind of a newbie in PHP but even I think this is not normal.
My code blocks in the followoing line all the time:
$insert = 'INSERT INTO boleia VALUES ('.$nick.', '.$data_format.', '.$custo.', '.$dest_origem.', '.$dest_destino.', NULL, '.$matricula.');';
I tried with double quotes and with the variables inside those double quotes and nothing.
Any idea?
Your PHP code is syntactically correct but the generated SQL is not because you are not using quotes to delimit the values.
You can do this:
$insert = 'INSERT INTO boleia VALUES ("'.$nick.'", "'.$data_format.'", "'.$custo.'", "'.$dest_origem.'", "'.$dest_destino.'", NULL, "'.$matricula.'");';
or this:
$insert = "INSERT INTO boleia VALUES ('".$nick."', '".$data_format."', '".$custo."', '".$dest_origem."', '".$dest_destino."', NULL, '".$matricula."');';
you can also do this:
$insert = "INSERT INTO boleia VALUES ('$nick', '$data_format', '$custo', '$dest_origem', '$dest_destino', NULL, '$matricula');";
but none of that ways are recommended because you are vulnerable to SQL Injections!
How to prevent SQL Injections?
To prevent that you must escape the values using the appropriate function for your DB, for example, since you are using PostgreSQL you must use pg_escape_string() for every value:
$insert = 'INSERT INTO boleia VALUES ("'.pg_escape_string($nick).'", "'.pg_escape_string($data_format).'", "'.pg_escape_string($custo).'", "'.pg_escape_string($dest_origem).'", "'.pg_escape_string($dest_destino).'", NULL, "'.pg_escape_string($matricula).'");';
An other way would be using pg_prepare() with pg_execute()
pg_prepare($dbconn, "my_insert", 'INSERT INTO boleia VALUES ($1, $2, $3, $4, $5, NULL, $6);');
pg_execute($dbconn, "my_insert", array($nick, $data_format, $custo, $dest_origem, $dest_destino, $matricula));
Or even using pg_query_params()
pg_query_params($dbconn, 'INSERT INTO boleia VALUES ($1, $2, $3, $4, $5, NULL, $6);',
array($nick, $data_format, $custo, $dest_origem, $dest_destino, $matricula));
Each value in an insert query requires quotes around it unless it's a number or NULL.
$insert = "INSERT INTO boleia VALUES ('$nick', '$data_format', '$custo', '$dest_origem', '$dest_destino', NULL, '$matricula');";
If you use PDO you don't have to worry about quoting or escaping anything.
Example from this PDO Tutorial:
$stmt = $db->prepare("INSERT INTO table(field1,field2,field3) VALUES(:field1,:field2,:field3)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2, ':field3' => $field3));
$affected_rows = $stmt->rowCount();
You need to encapsulate the string values going in to the query.
E.g.
$insert = 'INSERT INTO boleia VALUES ("'.$nick.'", "'.$data_format.'", "'.$custo.'", etc.
You better use double quotes for the SQL strings as it will be easier for you later on to sport where you didn't encapsulate by the quotes your strings
$insert = "INSERT INTO boleia VALUES ('$nick', '$data_format', '$custo', '$dest_origem', '$dest_destino', NULL, '$matricula')";
People, common. The original question is only 1 (ONE) line long! It is exactly this:
$insert = 'INSERT INTO boleia VALUES ('.$nick.', '.$data_format.', '.$custo.', '.$dest_origem.', '.$dest_destino.', NULL, '.$matricula.');';
we don't have to fix here any non-escaped strings presuming he hasn't done it before, neither we should presume that he is using PostgreSQL just because we see it in the tags. He had a simple error - missing encapsulation of strings in the query. It is fixed, in it's simplest form, as this:
$insert = 'INSERT INTO boleia VALUES (\''.$nick.'\', \''.$data_format.'\', \''.$custo.'\', \''.$dest_origem.'\', \''.$dest_destino.'\', NULL, \''.$matricula.'\');';
And that's it!
If, and only if, we like to add some extra info, as of how to escape the strings in case this hasn't been done, or if we are better using double quotes since it is less human-error-prone in such case, or if there is a good PDO Tutorial to read.... it's all either an additional info after the exact answer to his problem, or a chatty-off-topic.
Cheers.
$db = new mysqli( some db data );
$nick = $db->real_escape_string( $nick );
$data_format = $db->real_escape_string( $data_format ); // this is probably not needed
$dest_origem = $db->real_escape_string( $dest_origem );
$dest_destino = $db->real_escape_string( $dest_destino );
$matricula = $db->real_escape_string( $matricula );
$insert = "INSERT INTO boleia VALUES ('$nick', '$data_format', '$custo', '$dest_origem', '$dest_destino', NULL, '$matricula')";
and you should be OK

Insert a PHP false into mysql

My MySQL table contains a tinyint(1) value that i use to store a true or false value.
I have the following PHP variables:
$name = '';
$description = '';
$active = true;
Now my SQL query is as follows:
$query = "INSERT into my_table (my_name, my_description, active) VALUES ('$name', '$description', $active) ";
This will only work if my value for $active is true. As soon as the active variable is false, php will insert an empty string, instead of a 0 and thus the query will fail.
What is the best method to use false in such a query?
Should i manually convert the false to a '0' string?
Is it better use stings on the PHP side right away? in other words declare: $active = '1';
or can i somehow get PHP to always convert false to a '0' string?
Thanks
Michael
Convert your variable to int:
intval($active)
First of all your values should be escaped using mysql_real_escape_string or mysqli_real_escape_string or other method suitable for your database connection to avoid sql injection then for your specific question regarding false you may do something like that:
$query = "INSERT into my_table (my_name, my_description, active) VALUES ('$name', '$description', ".($active?1:0) .")";
or casting $active to int should do the work too:
$query = "INSERT into my_table (my_name, my_description, active) VALUES ('$name', '$description', ".((int) $active)).")";
use a mysql_real_escape_string function...
$query = "INSERT into my_table (my_name, my_description, active) VALUES ('".mysql_real_escape_string($name)."', '".mysql_real_escape_string($description)."', ".mysql_real_escape_string (((int) $active))).")";

Categories