次のように、整数の有名な AlphaID 表現を作成する PHP 関数があります。
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が存在しないというエラーを最初に受け取りました。その後、実際に、使用しようとしていたデータベースとは別のデータベースで関数を作成したことに気付きました。
しかし、適切なデータベースで再度作成しましたが、同じエラーが発生しました。
だからここに質問があります:
- 私は何を間違えましたか?このようなことをしようとするのはこれが初めてで、正確にはわかりません
- 私の PHP コードの実装は有効な MySQL 対応物ですか? 何か見逃しましたか?
- この関数を「グローバル」にすることはできますか? つまり、必要なデータベースで利用できますか? 私が取り組んでいるアプリケーションでは、関連する 2 つのサブシステムを分離しておくために、2 つのデータベースを作成しました。
更新しました
どうやら、関数が作成されないという問題は DBNinja 側にあるようです。なぜなら、MySQL コンソールで直接ステートメントを実行したためです。同じ出力ステータスの0 行が影響を受けましたが、ステートメントで関数を効果的に使用できたので、関数は結局作成されました。
ただし、ルーチン自体に何か問題があるため、テストしたところ、結果の文字列は...「1つ先」でした。
たとえば、次の PHP コードを実行するとします。
echo alphaID( 2 );
これはbaaacを生成しますが、MySQL 関数はbaaadを返します。これは、整数3の AlphaID 表現になります。
これは間違っているだけでなく、最大 2147483647 に達したときに使用される INT 型をオーバーフローさせる可能性もあると思います