Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Вставка произвольной даты в таблицу MySQL в программе на PHP  (Прочитано 36951 раз)
0 Пользователей и 1 Гость смотрят эту тему.
andrystepa
Помогающий

ru
Offline Offline

« : 26-03-2009 12:12 » 

Есть база данных на MySQL. Пишу на PHP интерфейс пользователя. В частности надо добавлять в одну из таблиц базы записи о новых проектах. Запись включает название проекта, дату начала, дату завершения и его статус. Пользователь на Web странице вводит в текстовые поля эти данные. Я вставляю полученные строки в запрос:
Код:
$sql = "INSERT INTO Proj (Prj_name, Start_D, Stop_D, Status) VALUES ('$Pname', $startd, $stopd, 1);";

Но тут проблема - переменные $stastd и $stopd - это строки, а в таблице хранятся данные в виде числа секунд. Поэтому такой запрос MySQL не поймет. Если делать из консоли mysql - понимает, а средствами PHP - нет. Есть ли какая-нибудь функция конвертации строки с датой в понятный для MySQL формат?
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 26-03-2009 12:40 » 

есть Улыбаюсь

strtotime();
« Последнее редактирование: 26-03-2009 12:42 от Sla » Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
andrystepa
Помогающий

ru
Offline Offline

« Ответ #2 : 26-03-2009 13:56 » 

Посмотрел сюда:
http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
Нету там такой функции. Есть функция STR_TO_DATE(). Только вот опять в консоли срабатывает, а из-под PHP не хочет:
Код такой:
Код:
$sql = "INSERT INTO Proj (Prj_name, Start_D, Stop_D, Status) VALUES ('$Pname', SELECT STR_TO_DATE('$startd', %Y-%m-%d), 0, 1);";
$result = getquery($sql);
if ($result) {
print "<br>";
print $sql;
print "<br>";
$sql1 = "SELECT * FROM Proj;";
$result = getquery($sql1);
print <<<HERE
<div align="center">
HERE;
print showtable($result);
print <<<HERE
</div>;
HERE;
}
else { print "Query Error1";
$tsql = "SELECT STR_TO_DATE('$startd', '%Y-%m-%d');";
$res = getquery($tsql);
print"<br>";
print $res;
print "<br>";
print $sql;
}
Функция getquery($query) и showtable($result) - это мои функции. Одна - оболочка для mysql_query(), а вторая выводит таблицу из запроса. Обе работают без пробелем - уже не раз применял.
$startd - берется из текстового поля ввода на веб-странице. Вот что получается при добавлении:
Код:
Query Error1
 
STR_TO_DATE('2008-01-01', '%Y-%m-%d')
2008-01-01

  INSERT INTO Proj (Prj_name, Start_D, Stop_D, Status) VALUES ('Ангола', SELECT STR_TO_DATE('2008-01-01', %Y-%m-%d), 2009-10-01, 1);
Это то, что было на веб-странице, показывающей результат. Странно. Вроде вложенный запрос должен сработать, а выдает ошибку. В чем она?
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 26-03-2009 14:14 » 

а может так?
STR_TO_DATE('2008-01-01', '%Y-%m-%d')
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 26-03-2009 14:15 » 

strtotime();
так то для php
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
andrystepa
Помогающий

ru
Offline Offline

« Ответ #5 : 26-03-2009 14:21 » 

Попробовал. Нифига не изменилось. Только запрос на веб странице теперь печатается так:
Код:
INSERT INTO Proj (Prj_name, Start_D, Stop_D, Status) VALUES('Ангола', SELECT STR_TO_DATE('2008-01-01', '%Y-%m-%d'), 2009-10-01, 1);
Записан
McZim
Модератор

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #6 : 26-03-2009 14:32 » 

<?php

date('Y-m-d' ,strtotime($startd));

?>
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 26-03-2009 15:06 » 

что ты получаешь запросом?
SELECT STR_TO_DATE('2008-01-01', '%Y-%m-%d'), 2009-10-01, 1)

наверное надо
SELECT STR_TO_DATE('2008-01-01', '%Y-%m-%d'),  STR_TO_DATE('2009-10-01','%Y-%m-%d'), 1)
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 26-03-2009 15:08 » 

McZim, я думаю, что решение о дате, все же лучше отдать в СУБД
в php надо проверить только корректность формата даты
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
andrystepa
Помогающий

ru
Offline Offline

« Ответ #9 : 26-03-2009 17:37 » 

Странно. Попробовал отдельно напечатать:
Код:
print "результат преобразования: ";
print strtotime($startd));

В результате получил на странице:
 
результат преобразования:

И все! Что-то не так. Строку вводил в формате YYYY/mm/dd - то есть 2008/01/01 как написано в моем справочнике.
Записан
McZim
Модератор

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #10 : 26-03-2009 19:08 » 

Код:
<?php
$str = &#39;2009/03/26&#39;;

$date date(&#39;Y/m/d&#39; ,strtotime($str));
echo $date
?>

Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 26-03-2009 19:43 » 

andrystepa, почитай про strtotime, много интересного Улыбаюсь
по большому счету должно было вернуть -1
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
andrystepa
Помогающий

ru
Offline Offline

« Ответ #12 : 27-03-2009 07:08 » 

В преобразовании ошибку нашел: в функции strtotime(str, [int]) строку с датой надо ставить в кавычки. То есть для моего случая:
 strtotime("$startd");
 strtotime("$stopd");
Все поправил. Код получился такой:
Код:
$strd = strtotime("$startd");
$stfd = strtotime("$stopd");
$sql = "INSERT INTO Proj (Prj_name, Start_D, Stop_D, Status) VALUES('$Pname', '$strd', '$stfd', 1);";
print "<br>";
print "Используем следующий запрос:";
print "<br>";
print $sql;
print "<br>";
$result = getquery($sql);
if ($result) {
print "<br>";
print "<br>";
$sql1 = "SELECT * FROM Proj;";
$result = getquery($sql1);
print <<<HERE
<div align="center">
HERE;
print showtable($result);


в ответ получил следующее:
Код:
Используем следующий запрос:
INSERT INTO Proj (Prj_name, Start_D, Stop_D, Status) VALUES('Проект4', '1199134800', '1254340800', 1);


Вроде с запросом все в порядке. Дата преобразовалась. Ан нет. В таблице вижу такое:

Код:
mysql> SELECT * FROM Proj;
+--------+----------+------------+------------+--------+
| Prj_Id | Prj_name | Start_D    | Stop_D     | Status |
+--------+----------+------------+------------+--------+
|      2 | Проект1  | 2007-06-01 | 2010-06-01 |      1 |
|      3 | Проект2   | 1900-01-01 | 1900-10-01 |      0 |
|      4 | Проект3   | 1892-03-01 | 2007-10-01 |      0 |
|      6 | Проект4  | 0000-00-00 | 0000-00-00 |      1 |
+--------+----------+------------+------------+--------+
4 rows in set (0.00 sec)

То есть даты, зараза, опять вставились нулевые!
Почему? Что еще требуется?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #13 : 27-03-2009 07:40 » 

Код:
Используем следующий запрос:
INSERT INTO Proj (Prj_name, Start_D, Stop_D, Status) VALUES('Проект4', '1199134800', '1254340800', 1);

andrystepa, а что это за даты такие у тебя чудесные? Очень напоминает unix timestamp...

Внимательно читаем мануал!
http://dev.mysql.com/doc/refman/5.0/en/datetime.html

1.
Цитата
MySQL retrieves and displays DATETIME values in 'YYYY-MM-DD HH:MM:SS' format.

2.
Цитата
MySQL retrieves and displays DATE values in 'YYYY-MM-DD' format.

3.
Цитата
You can specify DATETIME, DATE, and TIMESTAMP values using any of a common set of formats:

  • As a string in either 'YYYY-MM-DD HH:MM:SS' or 'YY-MM-DD HH:MM:SS' format.
  • As a string in either 'YYYY-MM-DD' or 'YY-MM-DD' format.
  • As a string with no delimiters in either 'YYYYMMDDHHMMSS' or 'YYMMDDHHMMSS' format, provided that the string makes sense as a date.
  • As a string with no delimiters in either 'YYYYMMDD' or 'YYMMDD'  format, provided that the string makes sense as a date.
  • As a number in either YYYYMMDDHHMMSS or YYMMDDHHMMSS format, provided that the number makes sense as a date.
  • As a number in either YYYYMMDD or YYMMDD format, provided that the number makes sense as a date.
  • As the result of a function that returns a value that is acceptable in a DATETIME, DATE, or TIMESTAMP context, such as NOW() or CURRENT_DATE.

4.
UNIX TIMESTAMP не является календарным типом - это целое число. По этому его нельзя присваивать и сравнивать с датами напрямую - для этого есть функции преобразования.
http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_from-unixtime
http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_unix-timestamp
« Последнее редактирование: 27-03-2009 07:42 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
andrystepa
Помогающий

ru
Offline Offline

« Ответ #14 : 27-03-2009 08:31 » 

То есть для того чтобы строку с датой, введенную пользователем вставить в базу данных MySQL как дату надо ее сначала преобразовать в UNIX_TIMESTAMP а потом снова преобразовать в дату? А напрямую нельзя?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #15 : 27-03-2009 09:23 » 

andrystepa, не придумывай сложностей на свою голову!

В каком формате у тебя дата в программе? Ты мануал по PHP смотрел?

Функция strtotime() возвращает unix timestamp. Дата в формате unix timestamp - это число, означающее количество секунд, прошедшее с 1.01.1970 00:00:00.

Теперь тебе надо это преобразовать в один из разрешенных для вставки в столбец DATE форматов (см. мой пост выше).
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
andrystepa
Помогающий

ru
Offline Offline

« Ответ #16 : 27-03-2009 12:53 » 

Жалко. Если бы была функция преобразующая напрямую - это было бы проще чем использовать две функции - преобразовать сначала в UNIX_TIMESTAMP, а потом в нужный формат.
Записан
McZim
Модератор

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #17 : 27-03-2009 12:58 » 

andrystepa, есть решение!!! Сразу помещать в переменную данные нужного формата.
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
andrystepa
Помогающий

ru
Offline Offline

« Ответ #18 : 27-03-2009 18:49 » 

McZim,
А как это делается, если не секрет? Я ведь получаю данные из текстового поля ввода на web странице. А это текстовая строка. Я видел на web страницах поля выбора даты с календарем. Может они выдают данные в виде даты. Но как они реализуются я понятия не имею.
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #19 : 27-03-2009 19:11 » 

andrystepa, давай с календарем разберемся позжее Улыбаюсь
1.  Получить данніе от пользователя.
2. Провести валидацию данніх
  2.а проверить правильность формата данных, например dd-mm-yyyy
  2.b проверить диапазон дат (29-02, 28-02
3. Преобразовать в unixstamp 
4. Преобразовать в формат даты СУБД

4 необходимых условия
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
andrystepa
Помогающий

ru
Offline Offline

« Ответ #20 : 09-04-2009 13:09 » 

Черт побери. Теперь не удается правильно составить запрос на вставку. Я сделал такой запрос:
Код:
INSERT INTO Proj (Prj_name, Start_D, Stop_D, Status) VALUES ('Ангола', Start_D, Stop_D, 1) SELECT FROM_UNIXTIME(1199134800) AS Start_D, FROM_UNIXTIME(1254340800) AS Stop_D;
ERROR 1064 (42000): 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 'SELECT FROM_UNIXTIME(1199134800) AS Start_D, FROM_UNIXTIME(1254340800) AS Stop_D' at line 1

Ошибка! Я видимо неправильно составил запрос. Но не знаю в чем. Шаблон  для запроса я взял в книжке по MySQL 5 Кузнецова Симдянова. Что неправильно?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #21 : 09-04-2009 13:37 » 

andrystepa, видимо ты совсем не понимаешь SQL...
VALUES и SELECT никак не могут быть в одном INSERT!
Прочти внимательно мануал - синтаксис команд там описан.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
andrystepa
Помогающий

ru
Offline Offline

« Ответ #22 : 10-04-2009 06:12 » 

Спасибо. Меня сбила с толку книга "MySQL 5  в подлиннике" авторы Максим Кузнецов, Игорь Симдянов. Там в пункте 24.8  "Вложенные запросы в операторе INSERT" был такой пример:
Код:
INSERT INTO new_orders VALUES (id_order, ordertime, product, user) SELECT orders.id_order AS id_order, orders.ordertime AS ordertime,
             --> products.name AS product FROM orders, users, products WHERE orders.id_user = users.id_user AND
            -->  orders.id_product = products_id_product;

В соответствии с этим примером я и сделал запрос. Что-ж, значит врут писатели.... А эту книжку многие рекомендовали.
Работает вот такая конструкция ( это код в странице на php):
Код:
$strd = strtotime("$startd");
$stfd = strtotime("$stopd");
$sql = "INSERT INTO Proj (Prj_name, Start_D, Stop_D, Status) SELECT '$Pname', FROM_UNIXTIME($strd), FROM_UNIXTIME($stfd), 1;";

где $startd, $stopd и $Pname получены из формы ввода. То есть тот же запрос, только без VALUES.
Записан
RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 10-04-2009 06:29 » 

andrystepa, вот тебе функция, которая преобразовывает дату из строкового формата в Unix Stamp с проверкой входных данных. Воспринимаются входные строки:
ДД.ММ.ГГ, ДД.ММ.ГГГГ, ДД/ММ/ГГ, ДД/ММ/ГГГГ, ДД\ММ\ГГ, ДД\ММ\ГГГГ
Код:
//преобразовывает дату из строкового формата в штамп
function dt_str_to_date($value) {
    $match = 0;
    if( ereg('^([0-9]{1,2})[/|.|\\]([0-9]{1,2})[/|.|\\]([0-9]{2,4})$',
            $value, $match) ) {
        if( ($ret = strtotime("{$match[2]}/{$match[1]}/{$match[3]}")) ) {
            return $ret;
        }
    }
    return NULL;
}
Если дату преобразовать не удалось, то функция вернёт NULL, что ты легко сможешь проверить.
Записан

Любимая игрушка - debugger ...
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #24 : 10-04-2009 06:49 » 

RuNTiME, не сканает

99/99/9999 чего ereg вернет?
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #25 : 10-04-2009 06:53 » 

не большой спец в регулярках

ereg('^([0-3]?[0-9]{1,2})[/|.|\\]([0|1]?[0-9]{1,2})[/|.|\\]([0-9]{2,4})$');

присмотрелся, кажется так лучшее

ereg('^([0-3]?[0-9]?)[/|.|\\]([0|1]?[0-9]?)[/|.|\\]([0-9]{2,4})$');

но и тут
39/19/9999
« Последнее редактирование: 10-04-2009 06:56 от Sla » Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #26 : 10-04-2009 07:40 » new

Sla, варианты с 39/19/9999, 99/99/9999 ну и тому подобные не пропустит strtotime()... так что проблемы не вижу... регулярки в основном тут используются для того, чтобы распарсить дату и выставить в правильном порядке день, месяц и год для strtotime(). Улыбаюсь
« Последнее редактирование: 10-04-2009 07:58 от RuNTiME » Записан

Любимая игрушка - debugger ...
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines