@kamtm

Правильно ли сформирован запрос на php, mysql?

Добрый день!

В книге встретил такое решение, для удобство сократил переменные в запросе:

$insert_sql = sprintf("INSERT INTO users " .
                                "(first_name, last_name) " .
                               "VALUES ('%s', '%s') ; " ,
                                mysql_real_escape_string($first_name),
                                mysql_real_escape_string($last_name));


Вопрос 1.
Нужна ли точка с запятой, перед скобкой в 3-ей строке? Если ее убрать, то все работает тоже.

Вопрос 2.
У меня первое поле user_id - auto_increment
Есть поле user_adddate- дата регистрации, тип bigint(20)

Правильно ли я сформировал запрос, указав NULL для поля user_id, и %d, для поля user_adddate?

$insert_sql = sprintf("INSERT INTO users (user_id,user_name,user_adddate) VALUES (NULL,'%s','%d')",
$user_name,TIME());


Как вариант, был такой запрос:
$insert_sql = sprintf("INSERT INTO users (user_id,user_name,user_adddate) VALUES ('%s','%s','%d')",
NULL,$user_name,TIME());
  • Вопрос задан
  • 3047 просмотров
Решения вопроса 1
nowm
@nowm
1. Точка с запятой необязательна, если выполняется только одна инструкция. В вашем случае её можно не писать, так как выполняется только одна инструкция «INSERT». Если инструкций несколько, то каждая инструкция обязательно должна заканчиваться точкой с запятой (кроме последней инструкции, кажется — там не обязательно).

2. Да, запрос правильный.

Тот запрос, который у вас был «как вариант», не будет работать, потому что вы пытаетесь нормальный PHP-шный NULL скопировать в строку. Там не появится слово «NULL» в итоге, так как вместо него подставится пустая строка. Итоговый запрос будет выглядеть примерно так:

INSERT INTO users (user_id, user_name, user_adddate) VALUES ('', 'user', '1404721764')


У вас здесь сразу две ошибки. Первая — вы передаёте значение NULL, а нужно передавать строку со словом «NULL». Вторая — вы пытаетесь сгененрировать строку так, что у вас слово «NULL» будет в SQL-запросе стоять в кавычках. В таком случае это для SQL-сервера будет считаться не значением «NULL», а строкой. Будет выдана ошибка, потому что у вас user_id — целочисленное, а вы пытаетесь в него писать строку. Правильнее будет так (разобью на строки для читаемости):

<?php
$insert_sql = sprintf("
    INSERT INTO users (user_id, user_name, user_adddate) 
    VALUES (%s, '%s', %d)
", 'NULL', $user_name, time());
?>


Со sprintf вы движетесь в правильном направлении. После этого вам будет легко понять принцип работы подготовленных запросов PDO, которые я вам советую использовать вместо mysql_*-функций.

<?php
/* 
 * Инициализация. Эту строку нужно писать там, 
 * где вы делаете mysql_connect. А сам вызов mysql_connect 
 * и прочего сопутствующего можно удалить.
 */
$db = new PDO('mysql:dbname=testdb;host=127.0.0.1', 'dbuser', 'dbpass');

// . . .

/* 
 * Вставляемые переменные заменяются знаками вопроса. Никаких кавычек
 * тут ставить не нужно — PDO сам поставит их в нужном месте.
 */
$sth = $db->prepare('INSERT INTO `users` (user_id, user_name, user_adddate) VALUES (NULL, ?, ?)');

/* 
 * Передача значений в запрос происходит в виде массива;
 * порядок элементов в массиве имеет значение. 
 * $user_name — первый элемент, значит его значение подставится 
 * на месте первого знака вопроса. time() — второй элемент, значит
 * его результат подставится вместо второго «?»
 */

$sth->execute( array($user_name, time()) );
?>


В запросе выше я добавил NULL прямо в строку, чтобы сильно не загоняться, так как для его добавления нужна дополнительная работа. С дополнительной работой это выглядит примерно так:

<?php 
// . . . 

$sth = $db->prepare('INSERT INTO `users` (user_id, user_name, user_adddate) VALUES (?, ?, ?)');

/*
 * Важный момент: нельзя писать
 * $sth->bindParam(1, NULL, PDO::PARAM_NULL);
 * Перед тем, как биндить NULL, его нужно присвоить переменной 
 * и биндить уже эту переменную. Иначе будут выскакивать ошибки.
 */
$null_value = NULL;
$sth->bindParam(1, $null_value, PDO::PARAM_NULL);

$sth->bindParam(2, $user_name, PDO::PARAM_STR);
$sth->bindParam(3, time(), PDO::PARAM_INT);

/*
 * Так как параметры уже переданы с помощью bindParam-ов,
 * в вызов execute не нужно ничего добавлять.
 */
$sth->execute();
?>


По поводу NOW() или CURDATE(). У вас выскакивает ошибка потому, что это не функции PHP. Это функции MySQL и их нужно писать в запросе как есть — они выполняются не в интерпретаторе PHP.

Как я понял, вы пытались что-то вроде этого делать:

<?php
$insert_sql = sprintf("
    INSERT INTO users (user_id, user_name, user_adddate) 
    VALUES (%s, '%s', %d)
", 'NULL', $user_name, NOW());
?>


А нужно так:
<?php
$insert_sql = sprintf("
    INSERT INTO users (user_id, user_name, user_adddate) 
    VALUES (NULL, '%s', NOW())
", $user_name);
?>


Так же, если вы добавляете user_adddate с помощью NOW() или CURDATE(), лучше для этого столбца изменить тип с bigint(20) на datetime.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Если Вы только изучаете PHP, то сразу откажитесь от использования функций mysql_*, они уже больше года в статусе deprecated. Используйте mysqli_* или PDO с параметризованными запросами.
По вопросам:
1. Точка с запятой не обязательны.
2. Для поля AUTO_INCREMENT значение указывать не надо, его автоматически генерирует сервер. Дату надо хранить в поле с типом DATE, DATETIME или TIMESTAMP, соответственно присваивать CURDATE() или NOW().
Ответ написан
morozovdenis
@morozovdenis
тут ошибка ещё раньше - вы руками составляете insert

используйте высокоуровневые обёртки

есть open source framework-и на пхп, посмотрите как они генерят запросы - там есть ответы на ваши вопросы, йоу
Ответ написан
Комментировать
mysql_query("INSERT INTO users (user_id,user_name,user_adddate) VALUES ('',".$user_name.",".TIME().")");


Зачем вам sprintf не совсем понятно.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы