Javascript-форум (https://javascript.ru/forum/)
-   Серверные языки и технологии (https://javascript.ru/forum/server/)
-   -   Как записать массив в базу mysqli. (https://javascript.ru/forum/server/66707-kak-zapisat-massiv-v-bazu-mysqli.html)

wadim 04.01.2017 18:11

Как записать массив в базу mysqli.
 
Всем привет! Запись везде почти происходит, но в 1-2 местах ни как. Вот приблизительный код(основной слишком большой чтобы приводить):


$arr13= array('100','93','94');
$StrSerialize= json_encode($arr13);

mysqli_query($myConnect, "INSERT INTO `Fron` (id, Fron) VALUES ('{$str}', '{$StrSerialize}') ");

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

читаем с базы:

$arrFron= json_decode($arr[Fron]);


изменяем данные (тут и начинаются проблемы, не с изменением, а с записью далее):

$arrFron[]= strval($arrSmegnie2[$i9]);


запись в базу:

$StrSerialize= json_encode($arrFron);

mysqli_query($myConnect, "UPDATE `{$Fron}` SET `Fron` = '{$StrSerialize}' WHERE `id` = '{$id}' LIMIT 1 ");


Запись вообще не происходит, проблема в изменении данных, по идее все должно работать, я думаю касячные функции типа json_encode и
Serialize, есть ли другие методы записи массива в базу? Не хочется писать свой json_encode.

Данные записи-чтения:

После начального заполнения базы имеем: ["94"]
после изменения данных при последующей записи в базу имеем: ["94","100"]

То есть перед конечной записью(та которая не работает) я проверяю что пишу и меня устраивает, так как ["94","100"] это то что нужно, но запись не происходит. Возможно там пробелы или спец символы, которые не видны, ни знаю почему не пишет. Скорее что-то происходит на стадии изменения данных, но там ни чего не должно происходить, так как я далеко не первый раз программирую и не представляю как более профессионально там написать код, там нет или почти нет вариантов. Вину валю на json_encode. Поле Fron имеет тип text.

laimas 04.01.2017 18:18

Что есть этот массив?

wadim 05.01.2017 06:41

Цитата:

Сообщение от laimas (Сообщение 439685)
Что есть этот массив?

Не понял вопроса, что значит "Что есть этот массив"?
Обычный массив, имеет вид ["94","100"] или [94,100] - пробовал оба варианта, в этот массив происходит запись элемента ($arrSmegnie2[$i9]) другого массива, в свою очередь массив $arrSmegnie2 получен таким образом: $arrSmegnie2= $arrSmegnie;
Массив $arrSmegnie является глобальной переменной, в которую происходит запись из функции, в функции имеем: $arrSmegnie[]= $arrSmegniePro[$i5];

Массив $arrSmegniePro получен через мою программу, эта программа выводит массив так: document.write(a);
где а и есть массив $arrSmegniePro, просто с документа копированием берем строку массива и помещаем вручную в массив $arrSmegniePro.
Ошибка может быть при копировании, может захватились пробелы или спец символы, но массив обрабатываю trim() и приведением к числу.
Еще проблема может быть в $arrSmegnie2= $arrSmegnie;
Но я ни знаю как проще переписать массив. В общем проблемы по идее не должно быть, но она есть - вообще не происходит запись в базу.

laimas 05.01.2017 06:51

Цитата:

Сообщение от wadim
Не понял вопроса, что значит "Что есть этот массив"?

Назначение массива, что им определяется и для чего он служит. Должны быть веские основания для того, чтобы данные, которые подвержены изменениям вставлять в базу как сериализованные или json строкой. По уму этого нужно избегать.

wadim 05.01.2017 10:13

Извиняюсь, но массивов у меня не один и разбирать зачем они нужны не имеет смысла, должен быть массив (нужен), по другому ни как, можно в отдельную таблицу, но это геморой. Какие веские основания? Для чего тогда сериализация или json существуют? Я правильно понял что массив лучше не пихать в одно поле? Как его тогда - в разные поля, какие есть варианты?

laimas 05.01.2017 10:35

Странно однако суждение. К примеру идентификаторы заявок/заказов, это тоже массив. Как его нужно хранить в базе?

Нельзя в сериализованных данных сделать произвольную выборку, изменить их, и произвести другие прочие операции, которые составляют большую часть sql-запросов. Это можно сделать, но только посредством больших накладных расходов.

А держать строку только потому, что ее можно извлечь, преобразовать, а затем сохранить, так это ведь тоже дополнительная нагрузка. В таком случае уж приложение, которое использует эти данные и должен их модифицировать, а sql только вставлять/обновлять.

Что касается json_ecode, то она тут не причем, а то что в массиве могут быть пробелы, это не есть ошибка.

wadim 05.01.2017 11:06

Так я использую json_encode, вроде не работаю с сериализованными данными. Вообще нужно в одно поле запихнуть, сериализацией или строкой или иначе, мне пока все-равно, единственное что желательно - это возможность не вооруженным глазом видеть запись в базе, а не в бинарике к примеру. Так модификация данных и происходит в приложении php, как мне составить sql для поля в котором: 94,100 и что тогда в поле? Я думал что строка. Мне нужно удалить к примеру 94 или добавить 101. Наверное Вы имели в виду подобное: mysqli_query($myConnect, " UPDATE `red` SET `red` = CONCAT(`red`, ',' , '{$Log}') ");
С этого я начинал, работает еще хуже, мож запрос не правильный?

laimas 05.01.2017 11:40

База данных же не для того, чтобы в ней в РМА или подобном удобно было видеть все сразу и поэтому строка. Не важно сериализаиция или json, последняя ведь тоже строка.

Сравните, при значении как [94, 100], чтобы удалить 94 нужно извлечь, изменить, обновить. А если это записи, то DELETE/UPADATE WHERE field=94. Что эффективнее?

Если уж строка, то ПО запросил данные -> отработал -> REPLACE или UPDATE.

Но если с данными этого массива связаны данные, то хранение их как строка, это вообще самоубийство.

wadim 05.01.2017 12:22

Вот как Вы написали так и делаю, но в одном месте проги не работает, во всех остальных местах пока не выявил проблем. Стало быть скорее проблема в данных, а главное не способности mysqli съедать то, что дают, эта база очень капризная. С данными массива наверно связаны данные:
Делаю поиск, в том числе выбрав строку из базы, сделав массив, найдя значение в массиве, далее добавив другое значение в массив, далее массив в строку и в базу.
Мне желательно хранить массив в одном поле, mysqli в этом плане плох? Почему самоубийство? Напишите пожалуйста полный код как хранить массив в одном поле, а также другие варианты хранения/изменения/записи массива.

laimas 05.01.2017 12:32

Проблемы в данных, вернее сказать в их преобразовании нет. Скорее проблема в том, что вы не подготавливаете данные для запроса - экранировать их нужно. Коли используется mysqli, то используйте подготовленные запросы, либо производите сами экранирование перед записью.

Почему самоубийство если связаны - потому, что если рассматривать этот набор как ключи чего-то найденного, то их нельзя будет связать с найденным. Простой пример, есть заявки - ключ => значение. Необходимо удалить заявки значение которых равно N. Попробуйте решить эту задачу средствами sql, если ключи заявок, это строка и не важно в каком формате.

wadim 05.01.2017 13:02

Экранировал, решать задачу нет времени, я тут Вам свою задачу решить предлагаю вообще то!

laimas 05.01.2017 13:22

Какую задачу? О возможных причинах я сказал. Записать в базу можно что угодно. Если данные подготовлены, то обрезать их может только лимит установленный на длину поля VARCHAR.

wadim 05.01.2017 13:24

Экранировал 2 способами: $str= str_replace("'","\'",$str);
$str= mysqli_real_escape_string($str);
Не помогло. Я думаю Ваша задача про заявки решаема. Времени нет полностью решать ее. Я тут известную Вам задачу решить не могу.

laimas 05.01.2017 14:45

Цитата:

Сообщение от wadim
Экранировал 2 способами

$str= str_replace("'","\'",$str);

Экранируется вот так

$str= mysqli_real_escape_string($str);

А еще правильнее, в рамках mysqli и PDO использовать подготовленные запросы. Но, если речь о наборе чисел, то:

$a = [1, 2, 3];
echo json_encode($a); //[1, 2, 3] экранирование не требуется

$a = [1, "2", 3];
echo json_encode($a); //[1, "2", 3] нужно экранировать или
echo json_encode($a, JSON_NUMERIC_CHECK); //[1, 2, 3] экранирование не требуется

//но если данные извне и ожидаем только числа, то:
$a = array_map('intval', $a);
$json = json_encode($a);
//и с записью этой строки проблем не будет
"UPDATE table SET field='$json'"


Понял о какой задаче. Решать можно многое, но в данном случае большой кровью.

wadim 06.01.2017 10:15

Все заработало, возможно было дело в том что Вы написали, а так основная ошибка была в логике скрипта. Но в любом случае большое спасибо. Еще остался вопрос, как удалять и изменять(а также другие операции проводить) данные в строке-массиве, который в одном поле базы. Вот пример который у меня работает, но не всегда:
mysqli_query($myConnect, " UPDATE `red` SET `red` = CONCAT(`red`, ',' , '{$Log}') ");
Напишите пожалуйста подобные строки в таком же синтаксисе, я имею в виду не в ООП и в других вариантах.

laimas 06.01.2017 17:56

Цитата:

Сообщение от wadim
как удалять и изменять(а также другие операции проводить) данные в строке-массиве, который в одном поле базы.

Те кто понимают, что запаковать данные, надо которыми требуется постоянно производить операции, делать выборку по ним как произвольную так и по условиям, это удавка на шее, тот никогда подобным образом данные хранить не будет. А не будет именно потому, что как раз сделать это будет весьма затруднительно, а во многих случаях и не возможно. Я вам об этом сказал сразу, но ... Так что мне сказать нечего по данному поводу.

Вот здесь также думают что строка в одном поле, это удобно и круто, а потом маются.

wadim 07.01.2017 05:03

Я все понимаю, быстродействие мне нужно, но удобство порой важней, мне нужно только удалять значение из строки-поля, удалять я могу, только запятые остаются, с этим может и справлюсь, просто хотел бы посмотреть на Ваше решение, мож оно будет лучше. Мне нужны варианты, чтобы был выбор, а ставить то или иное решение в виде панацеи я не стал бы и Вам не советую. Я читал о мнении что удобство порой важней даже производительности и согласен с этим. Массив я хочу запихивать так: $str= implode(',', $arr);
а не через json_encode. Будет ли это правильным?

laimas 07.01.2017 05:41

Я и не говорю о быстродействии, я говорю о невозможности выполнения задачи.

Оставьте в покое sql и возьмите к примеру строку "a, b, c, d, f". Считаем, что у вашего РНР нет функции explode(), а также регулярных выражений. Требуется заменить f на e.

Если мы знаем, что позиция f последняя, то это легко сделать. Также не будет затруднений если она будет первой, и даже в середине, и мы знаем эту позицию. Но если мы не знаем позиции, если символов в строке может быть сколь угодно, то задача кардинально усложняется - нужно получить подстроку до первой запятой, затем из остатка следующую подстроку до запятой и т.д. пока не обнаружим символ.

Теперь мысленно перенесите этот процесс замены в sql. Надо ли еще говорить, что это и есть причина по которой так данные в базе не хранят?

Если массив числа, то конечно не проблема просто объединять их разделителем.

wadim 07.01.2017 05:50

Мне замена не нужна, мне добавление и удаление нужны пока, понимаю что на будущее и можно оставить задел, но в будущем можно переписать и базу и код под новые условия, хотя это и может быть сложно до невозможности. Пока буду исходить из того что есть. Мне только нужно удалить к примеру 44 из 15,44,10. И знать могу ли я json_encode заменить на implode.

laimas 07.01.2017 06:20

А добавление и удаление разве не модификация? Если добавить в конец строки не проблема, то удалить в произвольном месте, это еще надо найти, а с какими трудностями это связано я уже устал говорить. Средствами sql бескровно этого не сделать, нет в mysql реализации замены по регулярному выражению.

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

Но хранить телефоны клиентов этой организации в строке через разделитель, до этого вряд ли бы вы додумались, так как каике-то нужно будет и удалять, по номерам нужно будет и выборку делать, а при добавлении новых нужно проверять есть ли такой номер в базе, и т.д., и т.п. К тому же, если хорошо думать, то и храниться номер будет ни как 8(999)... и с прочими вариациями, а только числа.

У вас может и меньший объем, строка короче, но как раз потому что вы данные вогнали в строку, вы и огребли проблем по полной. И это может быть еще только началом.

laimas 07.01.2017 06:24

Цитата:

Сообщение от wadim
И знать могу ли я json_encode заменить на implode.

Строка массива чисел объединенный в строку через запятую равна json-строке массив чисел, за исключением крайних символов - [ и ]. Объединяйте на здоровье, легче то от этого не станет.

wadim 07.01.2017 07:15

В mysql реализации есть замена по регулярному выражению. Я по крайней мере это сделал. Могу удалить 44 из строки 15,44,10, остается решить как удалить запятые - решу может быть. Данные хранятся так:
id qq arr
1 10 15,44,10
Происходит выборка при условии id = тому то.
Если я массив вынесу в отдельную таблицу, то мне придется в нее писать/удалять id, так как бывает нужно удалить полностью строку или создать строку в таблице, а это значит что придется со второй таблицей работать, в которую вынесем массив. К тому же удаление элемента в массиве-строке во второй таб, приведет к нулевым полям, вот так:
id1 id2 id3 ....................
15 12 16
0 13 0
10 0 0

Тоже хватит мароки. Есть ли есть другой вариант структуры - пишите, буду благодарен.

laimas 07.01.2017 08:02

В mysql есть поиск по регулярному выражению, замены нет. А если вы такое обнаружили, заменяйте сразу с запятой, что мешает?

Про удаление и будет id равное 0, это конечно глупость.

PS. Есть оператор REPLACE(), на здоровье, заменяйте, но, если к примеру есть "11,24,2,15" и надо заменить 2 на 7, то замена этим оператором ",2" на ",7", вернет результат "11,74,7,15". Шаблон регулярного выражения да еще замену по этому шаблону сюда вставить нельзя.

wadim 07.01.2017 08:32

Мешает то что при удалении ,44, мы получим 1510 из 15,44,10. Вообще при удалении из поля mysql мы часто имеем 0 или я сам пишу туда 0, так как мне важно что я после прочту.

laimas 07.01.2017 08:55

Я вам уже все сказал, больше сказать нечего. И вообще, REGEXP в mysql, это не Perl RegEXP в РНР, это простейшее для поиска.

Хотите без проблем управлять данными, значит представляйте их в подобающей структуре. То что какие-то 0 при этом получаются, так это глупости от непонимания. )

Либо сложные изменения, а тем более по условию производите не средствами sql.

wadim 08.01.2017 02:23

Если удаляем к примеру 44 хоть со строки, хоть с отдельного поля (поле =44) что остается? Ноль, или что напишешь, мне нужно чтобы программа при чтении нуля понимала, что данные равны нулю или сложнее - что данных нет. иначе не корректная работа проги будет.

laimas 08.01.2017 05:05

Если удаляем запись в базе, то ничего там не остается.

То что вы пишите умом не понять. То что вы описываете есть индексный массив, и если использовать массив [1, 2, 3], в котором удален 2, то и бог с ним, нет и не надо. Но если это массив ['key_1'=>1, 'key_2'=>2,'key_3'=>3] и мы также работаем с его ключами, которые постоянны, то либо у ключа есть значение, либо null/0. То есть если переложить на базу, то ключи этого массива, есть нечто определенное в базе, а массив, это связанная по этим ключам таблица. Ключи этой таблицы (как и их значения) могут быть удалены только тогда, когда удаляется запись из основной таблицы по этому ключу.

У вас же индексный массив, и коли как-то по нему задается связь, то длина такого массива (пусть изначально и без значений) должна быть задана, а иначе как?

Я спрашивал что это за массив, связан ли он как-то с чем-то, чего мне не известно, а посему обо всех аспектах судить сложно.

wadim 18.01.2017 18:25

У меня конкретный вопрос как из строки 15,44,10 путем sql запроса удалить 44, с ключами понятно, если я пишу 15,44,10 и в этой строке нет ключей, значит меня это устраивает, ключи получим при прочтении, мне не нужна связь ключей со значениями. Я удаляю значение, после сдвигаю ключи массива. Но все это и так понятно и работает, вопрос как sql запросом удалить значение со строки.

laimas 18.01.2017 19:47

Цитата:

Сообщение от wadim
У меня конкретный вопрос как из строки 15,44,10 путем sql запроса удалить 44

Я уже рассказывал какие есть для этого в MySQL средства, и то, что держать данные в базе, которые подвергаются таким изменениям, в виде строки, это геморрой. Что еще добавить?

psiklop 22.01.2017 09:29

я брал строку, преобразовывал json_decode, менял как надо, обратно json_encode и снова запись, действительно расстраивает, что база насилуется, но никогда не слышал, что можно менять строку прямо в базе, удалил 44 и не знаешь как удалить ,44
можешь рассказать как ты удалил 44?


Часовой пояс GMT +3, время: 20:20.