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.