SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 01.03.2023 16:51:53

egos
Участник
Зарегистрирован: 01.08.2022
Сообщений: 12

Выбор записи по основному символьному представлению идентификатора

Нужно выбирать запись только по основному символьному представлению идентификатора с учетом того, что поле с идентификаторами может быть не только символьного, но и целочисленного типа, обычно беззнакового. На данный момент в основном используются такие решения:
1) WHERE CAST(`id` AS CHAR)='{$id}';
2) WHERE `id`='{$id}' с последующим сравнением селектора и выбранного значения, как строк, например на PHP strcmp($id, $row['id']).

Есть ли более эффективное решение? Просьба не предлагать вариант с отдельным хранением признака, указывающего на тип поля.

Неактивен

 

#2 03.03.2023 00:52:05

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Выбор записи по основному символьному представлению идентификатора

Правда же, что у вас у каждой таблицы известен тип идентификатора? Вы же не меняете структуру таблицы постоянно? Если да, то вариант через равенство будет работать?

Неактивен

 

#3 03.03.2023 00:52:58

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2419

Re: Выбор записи по основному символьному представлению идентификатора

Удивительно очень выглядит то, что Вы хотите сделать.
Опишите пожалуйста подробней Вашу историю.

Если формально, то в PHP есть разница между равенствами == и ===.

то есть
$a = 3;
$b = '3';

if ($a == $b)
и
if ($a === $b)

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


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#4 03.03.2023 14:43:48

egos
Участник
Зарегистрирован: 01.08.2022
Сообщений: 12

Re: Выбор записи по основному символьному представлению идентификатора

paulus написал:

Правда же, что у вас у каждой таблицы известен тип идентификатора?

Речь об универсальном коде, который может работать с разными таблицами.

deadka написал:

Опишите пожалуйста подробней Вашу историю.

Ничего удивительного. Нужно выбирать запись только по основному символьному представлению идентификатора, т.е. чтобы нельзя было получить результативную выборку по селектору "100cats", "1e2" и т.п. для записи с числовым идентификатором 100.

Неактивен

 

#5 03.03.2023 15:48:30

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2419

Re: Выбор записи по основному символьному представлению идентификатора

1) Для того, чтобы индекс использовался нужно строгое равенство, то есть
WHERE CAST(`id` AS CHAR)='{$id}';
всяко не подойдёт, скорее id = ... нужно использовать.

2) Преобразовать 100cats в 100 можно множеством способов, как regexpом, так и просто str_replace всего того, что не [0-9] в пустую строку.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#6 04.03.2023 11:45:35

egos
Участник
Зарегистрирован: 01.08.2022
Сообщений: 12

Re: Выбор записи по основному символьному представлению идентификатора

deadka написал:

1) Для того, чтобы индекс использовался нужно строгое равенство, то есть
WHERE CAST(`id` AS CHAR)='{$id}';
всяко не подойдёт

Я это понимаю smile Поэтому и ищу более эффективное решение. Этот вариант убран из кода даже "детских" фреймворков лет 5 назад. Но все равно продолжает использоваться.

deadka написал:

2) Преобразовать 100cats в 100 можно множеством способов, как regexpом, так и просто str_replace всего того, что не [0-9] в пустую строку.

Наверное, вы не поняли. Нужно наоборот учитывать разницу между селектором 100cats и числовым идентификатором 100 в таблице, чтобы результативная выборка происходила только при взаимно однозначном соответствии 100 - 100, но не
100cats - 100
1e2 - 100
и т.п.

Неактивен

 

#7 05.03.2023 04:20:57

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Выбор записи по основному символьному представлению идентификатора

egos написал:

Речь об универсальном коде, который может работать с разными таблицами.

Универсальный код, который может работать с разными таблицами, знает название колонки. Что ему мешает знать ее тип, ну вот правда? smile

Но давайте поиграем в эту игру. Есть ли проблема в том, чтобы искать по равенству с кавычками?

root test> select * from strange;
+--------+--------+
| intkey | strkey |
+--------+--------+
|      1 | 1cats  |
|      2 | 2cats  |
|      3 | 3cats  |
|      4 | 4cats  |
|      5 | 5cats  |
|      6 | 6cats  |
+--------+--------+
6 rows in set (0,00 sec)

root test> select * from strange where intkey = '4';
+--------+--------+
| intkey | strkey |
+--------+--------+
|      4 | 4cats  |
+--------+--------+
1 row in set (0,00 sec)

root test> select * from strange where strkey = '4cats';
+--------+--------+
| intkey | strkey |
+--------+--------+
|      4 | 4cats  |
+--------+--------+
1 row in set (0,00 sec)
 

Неактивен

 

#8 05.03.2023 12:07:19

egos
Участник
Зарегистрирован: 01.08.2022
Сообщений: 12

Re: Выбор записи по основному символьному представлению идентификатора

paulus написал:

Универсальный код, который может работать с разными таблицами, знает название колонки. Что ему мешает знать ее тип, ну вот правда? smile

Название колонки всегда одинаковое (id), а вот типа два разных.

С символьным типом проблем нет (неоднозначность, связанная с символьной кодировкой и регистром букв, легко контролируется). Проблема с этим:
select * from strange where intkey = '4cats' wink

Неактивен

 

#9 05.03.2023 12:17:58

egos
Участник
Зарегистрирован: 01.08.2022
Сообщений: 12

Re: Выбор записи по основному символьному представлению идентификатора

egos написал:

С символьным типом проблем нет

Кроме той, что ввиду универсальности после выполнения запроса для него тоже приходится выполнять strcmp($id, $row['id']), чего можно было бы и не делать. Извлекать тип из самой выборки, например из объекта PHP типа mysqli_result, чтобы выполнять дополнительное сравнение по условию, слишком накладно.

Неактивен

 

#10 05.03.2023 20:54:06

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Выбор записи по основному символьному представлению идентификатора

А в чем проблема с 4cats? Найдется строка с четверкой, вы ее покажете или даже отфильтруете на стороне клиента.

Пока что для меня проблема звучит все еще надуманной. Вплоть до того, что зафиксировать название колонки вы можете, а тип — нет.

Неактивен

 

#11 06.03.2023 10:46:01

egos
Участник
Зарегистрирован: 01.08.2022
Сообщений: 12

Re: Выбор записи по основному символьному представлению идентификатора

paulus написал:

Найдется строка с четверкой, вы ее покажете или даже отфильтруете на стороне клиента.

Сейчас в основном и приходится фильтровать, только не на конечном клиенте, а в посредническом ПО на сервере (смотрите вариант 2 в первом сообщении). Оптимизация такой фильтрации тоже интересует, например в некоторых фреймворках вместо прямого сравнения строк сравниваются их длины, но этот прием не решает "проблему 1e2".

Неактивен

 

#12 06.03.2023 11:53:02

egos
Участник
Зарегистрирован: 01.08.2022
Сообщений: 12

Re: Выбор записи по основному символьному представлению идентификатора

Есть режимы, в которых выборку записей по id выполняет программный каркас приложения и только потом запускается контроллер. В этом случае программист изначально не контролирует тип поля (если не вносит изменения в программный каркас). И очень не хотелось бы, чтобы он начинал писать код контроллера с проверки селектора, когда поле с идентификаторами имеет числовой тип.

Добавление в структуру данных маршрутизатора признака, определяющего тип поля с идентификаторами или формат селектора, или регулярного выражения, определяющего формат селектора, для упомянутых режимов не предусмотрено.

Неактивен

 

#13 07.03.2023 21:23:03

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Выбор записи по основному символьному представлению идентификатора

Тогда у меня три предложения, насколько я понимаю, вы все три просмотрели.
1. Знать таки про тип поля. Зафиксировать, сходить в information_schema и запомнить, положить в конфиг-файл, что угодно.
2. Приводить все к строке. Кастим поле к строке, кастим значение к строке, сравниваем. Плюс — работает, как вы хотите, минус — не использует индексы никогда.
3. Сделать второе поле с индексом, которое всегда строка, и обновлять его, например, триггером. Плюс — есть индекс. Минус — поддержание боль и напоминает чем-то «зафиксировать тип данных»

Неактивен

 

#14 09.03.2023 11:48:13

egos
Участник
Зарегистрирован: 01.08.2022
Сообщений: 12

Re: Выбор записи по основному символьному представлению идентификатора

paulus написал:

3. Сделать второе поле с индексом, которое всегда строка, и обновлять его, например, триггером.

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

В общем всем спасибо. За темой буду продолжать следить. Так что если кого-то озарит интересная идея, пишите, не стесняйтесь! smile

Неактивен

 

#15 05.04.2023 09:49:43

egos
Участник
Зарегистрирован: 01.08.2022
Сообщений: 12

Re: Выбор записи по основному символьному представлению идентификатора

Нашли приемлемое решение своими силами. Оно заключается в том, чтобы сравнивать селектор и выбранный идентификатор, как строки, только когда выражение strlen($row['id']) == 0 || ord($row['id']) > 0x39 ложно, т.е. при "подозрении на число" (идентификатор начинается с цифры, знака "минус" и т.п.). В итоге фильтрующее выражение усложняется до

strlen($row['id']) == 0 || ord($row['id']) > 0x39 || strcmp($id, $row['id']) == 0


Это действительно приемлемое решение, т.к. символьные идентификаторы редко начинаются с цифры, знака "минус" и т.п. Многие из символов с ASCII-кодами < 0x3A являются недопустимыми для использования в символьных идентификаторах, а слеш, например, недопустим в качестве первого (и последнего) символа.

Неактивен

 

#16 05.04.2023 10:05:09

egos
Участник
Зарегистрирован: 01.08.2022
Сообщений: 12

Re: Выбор записи по основному символьному представлению идентификатора

Сравнение strlen($row['id']) == 0 можно убрать, если ord() может работать с пустой строкой. В PHP может.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson