Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 1
Нужно выбирать запись только по основному символьному представлению идентификатора с учетом того, что поле с идентификаторами может быть не только символьного, но и целочисленного типа, обычно беззнакового. На данный момент в основном используются такие решения:
1) WHERE CAST(`id` AS CHAR)='{$id}';
2) WHERE `id`='{$id}' с последующим сравнением селектора и выбранного значения, как строк, например на PHP strcmp($id, $row['id']).
Есть ли более эффективное решение? Просьба не предлагать вариант с отдельным хранением признака, указывающего на тип поля.
Неактивен
Правда же, что у вас у каждой таблицы известен тип идентификатора? Вы же не меняете структуру таблицы постоянно? Если да, то вариант через равенство будет работать?
Неактивен
Удивительно очень выглядит то, что Вы хотите сделать.
Опишите пожалуйста подробней Вашу историю.
Если формально, то в PHP есть разница между равенствами == и ===.
то есть
$a = 3;
$b = '3';
if ($a == $b)
и
if ($a === $b)
дадут разный результат, можно от этого попробовать оттолкнуться.
Неактивен
paulus написал:
Правда же, что у вас у каждой таблицы известен тип идентификатора?
Речь об универсальном коде, который может работать с разными таблицами.
deadka написал:
Опишите пожалуйста подробней Вашу историю.
Ничего удивительного. Нужно выбирать запись только по основному символьному представлению идентификатора, т.е. чтобы нельзя было получить результативную выборку по селектору "100cats", "1e2" и т.п. для записи с числовым идентификатором 100.
Неактивен
1) Для того, чтобы индекс использовался нужно строгое равенство, то есть
WHERE CAST(`id` AS CHAR)='{$id}';
всяко не подойдёт, скорее id = ... нужно использовать.
2) Преобразовать 100cats в 100 можно множеством способов, как regexpом, так и просто str_replace всего того, что не [0-9] в пустую строку.
Неактивен
deadka написал:
1) Для того, чтобы индекс использовался нужно строгое равенство, то есть
WHERE CAST(`id` AS CHAR)='{$id}';
всяко не подойдёт
Я это понимаю Поэтому и ищу более эффективное решение. Этот вариант убран из кода даже "детских" фреймворков лет 5 назад. Но все равно продолжает использоваться.
deadka написал:
2) Преобразовать 100cats в 100 можно множеством способов, как regexpом, так и просто str_replace всего того, что не [0-9] в пустую строку.
Наверное, вы не поняли. Нужно наоборот учитывать разницу между селектором 100cats и числовым идентификатором 100 в таблице, чтобы результативная выборка происходила только при взаимно однозначном соответствии 100 - 100, но не
100cats - 100
1e2 - 100
и т.п.
Неактивен
egos написал:
Речь об универсальном коде, который может работать с разными таблицами.
Универсальный код, который может работать с разными таблицами, знает название колонки. Что ему мешает знать ее тип, ну вот правда?
Но давайте поиграем в эту игру. Есть ли проблема в том, чтобы искать по равенству с кавычками?
Неактивен
paulus написал:
Универсальный код, который может работать с разными таблицами, знает название колонки. Что ему мешает знать ее тип, ну вот правда?
Название колонки всегда одинаковое (id), а вот типа два разных.
С символьным типом проблем нет (неоднозначность, связанная с символьной кодировкой и регистром букв, легко контролируется). Проблема с этим:
select * from strange where intkey = '4cats'
Неактивен
egos написал:
С символьным типом проблем нет
Кроме той, что ввиду универсальности после выполнения запроса для него тоже приходится выполнять strcmp($id, $row['id']), чего можно было бы и не делать. Извлекать тип из самой выборки, например из объекта PHP типа mysqli_result, чтобы выполнять дополнительное сравнение по условию, слишком накладно.
Неактивен
А в чем проблема с 4cats? Найдется строка с четверкой, вы ее покажете или даже отфильтруете на стороне клиента.
Пока что для меня проблема звучит все еще надуманной. Вплоть до того, что зафиксировать название колонки вы можете, а тип — нет.
Неактивен
paulus написал:
Найдется строка с четверкой, вы ее покажете или даже отфильтруете на стороне клиента.
Сейчас в основном и приходится фильтровать, только не на конечном клиенте, а в посредническом ПО на сервере (смотрите вариант 2 в первом сообщении). Оптимизация такой фильтрации тоже интересует, например в некоторых фреймворках вместо прямого сравнения строк сравниваются их длины, но этот прием не решает "проблему 1e2".
Неактивен
Есть режимы, в которых выборку записей по id выполняет программный каркас приложения и только потом запускается контроллер. В этом случае программист изначально не контролирует тип поля (если не вносит изменения в программный каркас). И очень не хотелось бы, чтобы он начинал писать код контроллера с проверки селектора, когда поле с идентификаторами имеет числовой тип.
Добавление в структуру данных маршрутизатора признака, определяющего тип поля с идентификаторами или формат селектора, или регулярного выражения, определяющего формат селектора, для упомянутых режимов не предусмотрено.
Неактивен
Тогда у меня три предложения, насколько я понимаю, вы все три просмотрели.
1. Знать таки про тип поля. Зафиксировать, сходить в information_schema и запомнить, положить в конфиг-файл, что угодно.
2. Приводить все к строке. Кастим поле к строке, кастим значение к строке, сравниваем. Плюс — работает, как вы хотите, минус — не использует индексы никогда.
3. Сделать второе поле с индексом, которое всегда строка, и обновлять его, например, триггером. Плюс — есть индекс. Минус — поддержание боль и напоминает чем-то «зафиксировать тип данных»
Неактивен
paulus написал:
3. Сделать второе поле с индексом, которое всегда строка, и обновлять его, например, триггером.
Да, это очевидный вариант решения. Однако модель описывает только одно поле, чтобы программист мог не различать числовой и символьный идентификаторы, когда они "зрительно" совпадают. Ввести дополнительное поле он может самостоятельно. Это обычно происходит, когда он вводит числовые идентификаторы в дополнение к обычным символьным. Но он точно так же может ввести числовые идентификаторы в дополнение к аналогичным символьным.
В общем всем спасибо. За темой буду продолжать следить. Так что если кого-то озарит интересная идея, пишите, не стесняйтесь!
Неактивен
Нашли приемлемое решение своими силами. Оно заключается в том, чтобы сравнивать селектор и выбранный идентификатор, как строки, только когда выражение strlen($row['id']) == 0 || ord($row['id']) > 0x39 ложно, т.е. при "подозрении на число" (идентификатор начинается с цифры, знака "минус" и т.п.). В итоге фильтрующее выражение усложняется до
Неактивен
Сравнение strlen($row['id']) == 0 можно убрать, если ord() может работать с пустой строкой. В PHP может.
Неактивен
Страниц: 1