Проблемы при создании функции MySQL

У меня есть функция PHP для создания этих известных AlphaID представлений целых чисел следующим образом:

function alphaID( $input ) {

$index = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

$base    = strlen( $index );
$input  += pow( $base, 4 );
$output  = '';

for( $i = floor( log( $input, $base ) ); $i >= 0; $i-- ) {

$bcp     = bcpow( $base, $i );
$start   = floor( $input / $bcp ) % $base;
$output .= substr( $index, $start, 1 );
$input   = $input - ( $start * $bcp );
}

return $output;
}

Кодирование, например, максимального целого числа, предоставленного PHP_MAX_INT константа (2147483647) вернется cwuCBb

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

Руководство по MySQL не совсем дружелюбно, но, ища кое-где, я пришел к следующему:

DROP FUNCTION IF EXISTS ENCODE_ALPHAID;

DELIMITER $$

CREATE FUNCTION ENCODE_ALPHAID( input integer ) RETURNS CHAR( 6 ) DETERMINISTIC

BEGIN

DECLARE output CHAR( 6 );

DECLARE letters CHAR( 62 );
DECLARE base TINYINT( 2 );

DECLARE iterator TINYINT( 2 );
DECLARE bcp CHAR( 9 );
DECLARE start TINYINT( 2 );

SET output   = '';

SET letters  = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

SET base     = CHAR_LENGTH( letters );
SET input    = input + POW( base, 4 );

SET iterator = FLOOR( LOG( base, input ) );

ENCODING: LOOP

SET bcp      = POW( base, iterator );
SET start    = FLOOR( input / bcp ) % base + 1;

SET output   = CONCAT( output, SUBSTR( letters, start, 1 ) );

SET input    = input - ( start * bcp );

SET iterator = iterator-1;

IF iterator < 0 THEN LEAVE ENCODING; END IF;

END LOOP ENCODING;

RETURN output;

END $$

DELIMITER ;

Но когда я запустил его через менеджер MySQL, я использую (DBNinja), видимо, ничего не происходит. После запуска запроса он показывает Затронут 0 ряд и я не уверен, является ли это ожидаемым результатом или нет.

Правильно или нет, функция не работала в любом случае, потому что, когда я пытался использовать ее в запросе:

SELECT ENCODE_ALPHAID( `c`.`cid` ) from `table` c WHERE `c.user` = 1

Я впервые получил сообщение об ошибке table.ENCODE_ALPHAID не существовало Затем я заметил, что, действительно, я создал эту функцию, находясь в другой базе данных, которую я пытался использовать.

Но я создал его снова, в соответствующей базе данных, но появилась та же ошибка.

Итак, вот вопросы:

  1. Что я сделал не так? Это первый раз, когда я пытаюсь сделать что-то подобное, и я не совсем уверен,
  2. Моя реализация кода PHP является действительным аналогом MySQL? Я что-то пропустил?
  3. Могу ли я сделать эту функцию «глобальной»? Я имею в виду, доступный для любой базы данных мне это нужно? Потому что для приложения, над которым я работаю, чтобы разделить две подсистемы, я создал две базы данных.

обновленный

Очевидно, что проблема с не создаваемой функцией находится на конце DBNinja, потому что я выполнил оператор непосредственно в консоли MySQL и, хотя с тем же статусом вывода Затронуто 0 строк, Я смог эффективно использовать функцию в выражении, поэтому функция была создана в конце концов.

Тем не менее, что-то не так с самой подпрограммой, потому что, когда я тестировал ее, полученная строка была … «впереди».

Например, если я запускаю следующий код PHP:

echo alphaID( 2 );

Было бы производить baaac, но функция MySQL возвращается baaad, который будет AlphaID представление целого числа 3

Мало того, что это неправильно, но я думаю, что это может также переполнить тип INT, используемый при достижении максимума 2147483647

0

Решение

Бруно,
из версии MySQL вам не хватает:

  1. $ input + = pow ($ base, 4);
  2. SUBSTR в PHP начинается с 0, в MySQL начинается с 1.
  3. Условие окончания цикла должно быть:

    ЕСЛИ итератор < 0 ТО
    Оставьте кодирование;
    END IF;

  4. При использовании CONCAT убедитесь, что вы не используете CONCAT NULL (вам следует инициализировать параметры)

Рутины всегда создаются в одной базе данных. Вы можете вызвать их в любом из них (если у вас есть права), включив имя базы данных в запрос:

call mydb.ENCODE_ALPHAID( 2147483647 );

Кроме того, при объявлении переменных вы можете использовать префиксы, чтобы переменные не смешивались с возможными именами столбцов / зарезервированными словами. Например, вместо «output» используйте «v_output».

1

Другие решения

Похоже, вы пропустили END IF; Не используйте зарезервированные слова для переменных. Если вы хотите пойти по злому пути, обязательно процитируйте их .ie `table«,. Обратите внимание на обратную галочку — не одиночные кавычки. На моей машине этот код возвращает ноль:

CREATE DEFINER=`root`@`localhost` FUNCTION `ENCODE_ALPHAID`(`input` INT)
RETURNS CHAR(6) DETERMINISTIC NO SQL SQL SECURITY DEFINER
BEGIN
DECLARE output CHAR(6);
DECLARE `index` CHAR(62);
DECLARE base TINYINT(2);
DECLARE iterator TINYINT( 2 );
DECLARE bcp CHAR( 9 );
DECLARE start TINYINT( 2 ); SET `index` = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
SET base = CHAR_LENGTH( `index` );
SET iterator = FLOOR( LOG( base, input ) );
ENCODING: LOOP
SET bcp = POW( base, iterator );
SET start = FLOOR( input / bcp ) % base;
SET output = CONCAT( output, SUBSTR( `index`, start, 1 ) );
SET input = input - ( start * bcp );
SET iterator = iterator-1;
IF iterator >= 0 THEN LEAVE ENCODING;
END IF;
END LOOP ENCODING;
RETURN output;
END;

введите описание изображения здесь

PS: на спине отметьте галочкой один. Я понятия не имею, как избежать уценки. А также eaid это более короткое имя, которое я использовал

0