Форум программистов, компьютерный форум, киберфорум
PHP: базы данных
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/7: Рейтинг темы: голосов - 7, средняя оценка - 5.00
133 / 118 / 34
Регистрация: 04.04.2018
Сообщений: 593
1

INSERT подготовленный запрос

10.02.2020, 08:45. Показов 1333. Ответов 11
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте.
Имеется массив данных, $data
Код
Array
(
    [0] => 1
    [1] => 2
    [2] => 5
    [3] => desc,names,counts
    [4] => 2020-02-10 08:08:24
    [5] => 1
    [6] => 2
    [7] => 78
    [8] => 5
    [9] => desc
    [10] => 1
    [11] => Мороженное
    [12] => asdfasdf
)
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$types = "";
    foreach($new_e as $k => $v){
        if(!empty($v)){
            $s++;
            $pl .= ($s == $ct)?"?":"?,";
            $data[] = $v;
            if (intval($v) == TRUE) $types .= "i";
            elseif(floatval($v) == TRUE) $types .= "d";
            else $types .= "s";
        }
    }
 
        $prepared = $link->prepare("INSERT INTO `store_product` (`".$imp_column."`,
                    `status`,`job_column`,`date_added`,`user_id`,`category`,`subcategory`,
                    `price`".$hidden.$column_count.",`name`,`description`) VALUES (".$pl.")");
        if($prepared == FALSE)
            die("Opps...");
        $result =  $prepared->bind_param($types,$data); // указывает на эту строку
            echo count($data) . "<br>" . $s . "<br>" . $types;
            #13
            #13
            #iiisiii iisiss
                if($result== FALSE)
                die("Opps_two...");  '
SQL
1
INSERT INTO `store_product` (`desc`,`names`, `status`,`job_column`,`date_added`,`user_id`,`category`,`subcategory`, `price`,`hiddens`,`counts`,`name`,`description`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,? )
Сам запрос выглядит так. Подскажите, пожалуйста, почему происходит ошибка
Warning: mysqli_stmt::bind_param(): Number of elements in type definition string doesn't match number of bind variables in
Когда их по 13
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.02.2020, 08:45
Ответы с готовыми решениями:

Не выполняется подготовленный запрос (PHP PDO ODBC + MS Access)
Добрый день Если пишу (глупо, конечно, получается, но всё же. так я проверял работает запрос...

Перенос параметра при INSERT в другой запрос INSERT
Здравствуйте. Есть таблица Сlient, в которую при INSERT ClientID присваивается инкрементом. На...

Запрос INSERT INTO как построить запрос правильно?
Народ помогите пожалуйста сделать запрос правильно. Имеется таблица users в ней имеется данные для...

Запрос INSERT
Искренне прошу прощения за такой тупой вопрос, но я реально не могу понять, что не так в этом...

11
1113 / 554 / 320
Регистрация: 21.06.2012
Сообщений: 1,854
10.02.2020, 09:14 2
u4en1k, до поля status у вас ещё два поля находится: `desc`,`names`
тогда вопрос: что находиться в переменной $imp_column ? Ожидается тоже 2 поля, но вы эту переменную заворачивайте в косые кавычки. Тогда получается одно поле.

И в переменной $types у вас 14 элементов а не 13
0
133 / 118 / 34
Регистрация: 04.04.2018
Сообщений: 593
10.02.2020, 09:33  [ТС] 3
sasha0012, все верно,
Цитата Сообщение от sasha0012 Посмотреть сообщение
Ожидается тоже 2 поля,
это и есть `desc`,`names` так как первоначально они имеют вид desc`,`names
Цитата Сообщение от sasha0012 Посмотреть сообщение
тогда вопрос: что находиться в переменной $imp_column ?
implode('`,`',$name_field'); то есть запрос собирается, их может быть разное кол-во. Поэтому их нужно завернуть.
Почему 14, а не 13, когда $types
iiisiiiiisiss
содержит 13 символов.

Добавлено через 1 минуту
Пробел для наглядности указал в первом примере, в $types.
0
1113 / 554 / 320
Регистрация: 21.06.2012
Сообщений: 1,854
10.02.2020, 10:00 4
bind_param - Количество переменных и длина строки types должны в точности соответствовать количеству параметров в запросе.

видимо придется вручную прописывать переменные через запятую:
PHP
1
$result =  $prepared->bind_param($types,$data[0],$data[1],....);
или в цикле крутить массив дата и по одному передавать в bind_param.
0
133 / 118 / 34
Регистрация: 04.04.2018
Сообщений: 593
10.02.2020, 10:18  [ТС] 5
sasha0012, вся сложность в том, что не будет такой возможности определить за ранее вручную сколько имеется полей и имеется значений.

Не по теме:

Сначала я читаю документации, пытаюсь найти ответы на просторах интернета, а после уже того, как пройдет много часов и задача остается не решенной спрашиваю на форуме.


И дело в том, что этот код работает без подготовленного запроса, а обрабатываются данные перед записью с помощью mysqli_real_escape_string
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ex =  $imp."','5','".$job_column."','".$date_comment."','".$id."','".$category."','".$subcategory."','".$price."'".$col.$counts. ",'".$name_category['subcategory']."','".$description;
    $e = explode("','",$ex);
    $ct = count($e);
    foreach($e as $k){
        $s++;
        if($s == $ct) 
        $v .= "'".mysqli_real_escape_string($link,$k) . "'";
        elseif($s < $ct)  
        $v .= "'".mysqli_real_escape_string($link,$k) . "',";
    }
 
        $insert = mysqli_query($link, "INSERT INTO `store_product` (`".$imp_column."`,
                    `status`,`job_column`,`date_added`,`user_id`,`category`,`subcategory`,
                    `price`".$hidden.$column_count.",`name`,`description`) VALUES (".$v." )");
0
1113 / 554 / 320
Регистрация: 21.06.2012
Сообщений: 1,854
10.02.2020, 10:36 6
Цитата Сообщение от u4en1k Посмотреть сообщение
И дело в том, что этот код работает без подготовленного запроса
конечно сработает, ведь в этом случае обойдётся без bind_param.

Дело в том что bind_param не может принимать массив, он даже не может принять просто список значений через запятую. Только значения в виде ссылок (если я не ошибаюсь).

Попробуйте так составить запрос:
PHP
1
$result = $prepared->bind_param($types, implode(',', $data));
Возможно сработает. Да капризная функция. С PDO такой проблемы нет, хотя и там свой подводные камни есть.

ещё так можно попробовать:
PHP
1
2
3
foreach($data as $key => $value){
    $result = $prepared->bind_param($types[$key], $value);
}
1
133 / 118 / 34
Регистрация: 04.04.2018
Сообщений: 593
10.02.2020, 10:47  [ТС] 7
sasha0012, К сожалению, ни одно из выше указанных Вами решений не сработало.

Не по теме:

Буду думать как уже встану, а на этой ноте пойду отдыхать. Хорошего дня, спасибо за помощь:)

0
1113 / 554 / 320
Регистрация: 21.06.2012
Сообщений: 1,854
10.02.2020, 14:55 8
u4en1k, какой красивый косяк вышел из за неправильного сравнения с true и использования функции не по назначению. Вот как раз на таких примерах и происходит самое продуктивное обучение.

iiisiiiiisiss - пятый элемент указан под типом "i" (числовой), а в массиве данных там: 2020-02-10 08:08:24. Это разве число? Тогда вопрос, почему записался "i"? Смотрим дге он определяется:
PHP
1
if (intval($v) == TRUE) $types .= "i";
1 - intval переводит значение в число а не проверяет тип данных на число. Используйте is_int
2 - если сравниваете булево значение, то всегда используйте сравнение по типу тоже:
PHP
1
if (is_int($v) === TRUE) $types .= "i";
Добавлено через 3 минуты
и с floatval такая же история:
PHP
1
elseif(is_float($v) === TRUE) $types .= "d";
0
133 / 118 / 34
Регистрация: 04.04.2018
Сообщений: 593
11.02.2020, 01:35  [ТС] 9
sasha0012,
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$arr =  array("1",
                "2",
                "5",
                "plombir,morojennoe,counts,name,description",
                "2020-02-11 00:57:38",
                "1",
                "2",
                "78",
                " 5",
                "plombir",
                "1",
                "Мороженное",
                "adsfasdfadsf"
            );
foreach($arr as $k => $v){
    # работает, вывод
    # iiissiiississ
 
     if (ctype_digit($v)) 
        $types .= "i";
     else
        $types .= "s";
 
     /* не работает
        вывод
        sssssssssssss
    
         if (is_int($v) == TRUE) $types .= "i";
         elseif (is_float($v)  == TRUE) $types .= "d";
         else $types .= "s";
        */
  unset($v); 
}
 echo $types;
Получил корректные значения
iiissiiississ
PHP
1
        $result =  $prepared->bind_param("iiissiiississ",$data);
Пробую таким образом, получаю ошибку, что и была.
подготовленный запрос имеет такой вид
SQL
1
INSERT INTO `store_product` (`plombir`,`morojennoe`, `status`,`job_column`,`date_added`,`user_id`,`category`,`subcategory`, `price`,`hiddens`,`counts`,`name`,`description`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
Эти же данные что выше указываю в коде
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
$new_e = array("1",
                "2",
                "5",
                "plombir,morojennoe,counts,name,description",
                "2020-02-11 00:57:38",
                "1",
                "2",
                "78",
                " 5",
                "plombir",
                "1",
                "Мороженное",
                "adsfasdfadsf"
            );
    $ct = count($new_e);
    $types = "";
    foreach($new_e as $k => $v){
        if(!empty($v)){
            $s++;
            $pl .= ($s == $ct)?"?":"?,";
            $data[] = $v;
        //  if (is_int($v) === TRUE) $types .= "i";
        //  elseif (is_float($v) === TRUE) $types .= "d";
       //       else $types .= "s";
           
            unset($v);
        }
    }
 
        $prepared = $link->prepare("INSERT INTO `store_product` (`".$imp_column."`,
                    `status`,`job_column`,`date_added`,`user_id`,`category`,`subcategory`,
                    `price`".$hidden.$column_count.",`name`,`description`) VALUES (".$pl.")");
        if($prepared == FALSE)
            die("Opps...");
        $result =  $prepared->bind_param("iiissiiississ",$data);
        // debug
        echo "<pre>";
        print_r($data);
        echo "</pre> " .
        count($data) . "<br>" . $s . "<br>" . $types. "<br>INSERT INTO `store_product` (`".$imp_column."`,
                    `status`,`job_column`,`date_added`,`user_id`,`category`,`subcategory`,
                    `price`".$hidden.$column_count.",`name`,`description`) VALUES (".$pl.")";
         
                if($result== FALSE)
                die("Opps_two...");
Тоже самое.
$data
Код
Array
(
    [0] => 1
    [1] => 2
    [2] => 5
    [3] => plombir,morojennoe,counts,name,description
    [4] => 2020-02-11 00:57:38
    [5] => 1
    [6] => 2
    [7] => 78
    [8] =>  5
    [9] => plombir
    [10] => 1
    [11] => Мороженное
    [12] => adsfasdfadsf
)
0
1113 / 554 / 320
Регистрация: 21.06.2012
Сообщений: 1,854
11.02.2020, 10:09 10
Цитата Сообщение от u4en1k Посмотреть сообщение
/* не работает
вывод
sssssssssssss
if (is_int($v) == TRUE) $types .= "i";
elseif (is_float($v) == TRUE) $types .= "d";
else $types .= "s";
*/
Ну как это не работает!? Ещё как работает! У вас в массиве все данные строковые! Числовые данные в массиве так задаются:
PHP
1
2
3
4
$arr =  array(1, //int
                2, //int
                5, //int
                "plombir,morojennoe,counts,name,description", //string
u4en1k, у вас не получиться передать в bind_param ни массив ни строки. Эта функция требует ссылки на значения (переменные). В общем без садомазо здесь не обойтись:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$arr = array("test 1",
                2,
                "test 3"
            );
foreach($arr as $v){
    if (is_int($v) === TRUE) $types .= "i";
    elseif (is_float($v) === TRUE) $types .= "d";
    else $types .= "s"; 
}
$prepared = $link->prepare("INSERT INTO `store_product` (`plombir`,`morojennoe`,`status`) VALUES (?,?,?)");
if(count($arr)===1)$result = $prepared->bind_param($types,$arr[0]);
if(count($arr)===2)$result = $prepared->bind_param($types,$arr[0],$arr[1]);
if(count($arr)===3)$result = $prepared->bind_param($types,$arr[0],$arr[1],$arr[2]);
.............................
var_dump($result);
0
133 / 118 / 34
Регистрация: 04.04.2018
Сообщений: 593
11.02.2020, 10:58  [ТС] 11
sasha0012, Если неизвестное кол-во значений?
0
1113 / 554 / 320
Регистрация: 21.06.2012
Сообщений: 1,854
11.02.2020, 11:41 12
Лучший ответ Сообщение было отмечено u4en1k как решение

Решение

Цитата Сообщение от u4en1k Посмотреть сообщение
Если неизвестное кол-во значений?
тогда mysqli_real_escape_string либо PDO

Добавлено через 29 минут
u4en1k, при работе с функцией mysqli_real_escape_string запомните одно правило: данные обработанные этой функцией, в sql запросе всегда заворачивайте в одинарные кавычки. Если в запрос нужно поставить число, то не нужно прогонять эту переменную через mysqli_real_escape_string, а просто приводите её к числовому типу. Пример:

PHP
1
2
$id_user = (int)$_POST['id_user'];
$txt = mysqli_real_escape_string($link,$_POST['txt']);
SQL
1
INSERT INTO `product` (`id_user`,`txt`) VALUES ($id_user, '$txt')
1
11.02.2020, 11:41
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.02.2020, 11:41
Помогаю со студенческими работами здесь

Не получается запрос INSERT INTO
Добрый вечер. Пытаюсь в файле сперва создать таблицу, затем заполнить её. Создание получилось, а...

INSERT запрос (MVC)
Доброго времени суток В начале месяца взялся за эту трудоемкую вещь - веб-разработку. Пытаюсь...

INSERT-запрос в MVC
Всем привет! Занимаюсь реализацией mvc модели. У меня есть база данных. Я вывожу из неё данные без...

Не работает запрос INSERT
$query=mysql_query(&quot;INSERT INTO `user`...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru