MySQL에서의 base64 부호화
하나의 테이블에서 blob col을 선택하고 base64로 인코딩하여 다른 테이블에 삽입합니다.DB와 앱을 통해 데이터를 라운드 트립하지 않고 이 작업을 수행할 수 있는 방법이 있습니까?
같은 기능을 찾고 있었는데 MySQL 5.6에 TO_BASE64와 FROM_BASE64라는 새로운 문자열 함수가 몇 개 있습니다.
부호화 문자열이 32바이트(스페이스)인 경우 http://wi-fizzle.com/downloads/base64.sql에서 함수에 오류가 발생합니다(예: BASE64_ENCODE(CONCAT(CHAR(15), CHAR(32)).여기 수정된 함수가 있습니다.
DELIMITER $$
USE `YOUR DATABASE`$$
DROP TABLE IF EXISTS core_base64_data$$
CREATE TABLE core_base64_data (c CHAR(1) BINARY, val TINYINT)$$
INSERT INTO core_base64_data VALUES
('A',0), ('B',1), ('C',2), ('D',3), ('E',4), ('F',5), ('G',6), ('H',7), ('I',8), ('J',9),
('K',10), ('L',11), ('M',12), ('N',13), ('O',14), ('P',15), ('Q',16), ('R',17), ('S',18), ('T',19),
('U',20), ('V',21), ('W',22), ('X',23), ('Y',24), ('Z',25), ('a',26), ('b',27), ('c',28), ('d',29),
('e',30), ('f',31), ('g',32), ('h',33), ('i',34), ('j',35), ('k',36), ('l',37), ('m',38), ('n',39),
('o',40), ('p',41), ('q',42), ('r',43), ('s',44), ('t',45), ('u',46), ('v',47), ('w',48), ('x',49),
('y',50), ('z',51), ('0',52), ('1',53), ('2',54), ('3',55), ('4',56), ('5',57), ('6',58), ('7',59),
('8',60), ('9',61), ('+',62), ('/',63), ('=',0) $$
DROP FUNCTION IF EXISTS `BASE64_ENCODE`$$
CREATE DEFINER=`YOUR DATABASE`@`%` FUNCTION `BASE64_ENCODE`(input BLOB) RETURNS BLOB
DETERMINISTIC
SQL SECURITY INVOKER
BEGIN
DECLARE ret BLOB DEFAULT '';
DECLARE done TINYINT DEFAULT 0;
IF input IS NULL THEN
RETURN NULL;
END IF;
each_block:
WHILE NOT done DO BEGIN
DECLARE accum_value BIGINT UNSIGNED DEFAULT 0;
DECLARE in_count TINYINT DEFAULT 0;
DECLARE out_count TINYINT;
each_input_char:
WHILE in_count < 3 DO BEGIN
DECLARE first_char BLOB(1);
IF LENGTH(input) = 0 THEN
SET done = 1;
SET accum_value = accum_value << (8 * (3 - in_count));
LEAVE each_input_char;
END IF;
SET first_char = SUBSTRING(input,1,1);
SET input = SUBSTRING(input,2);
SET accum_value = (accum_value << 8) + ASCII(first_char);
SET in_count = in_count + 1;
END; END WHILE;
-- We've now accumulated 24 bits; deaccumulate into base64 characters
-- We have to work from the left, so use the third byte position and shift left
CASE
WHEN in_count = 3 THEN SET out_count = 4;
WHEN in_count = 2 THEN SET out_count = 3;
WHEN in_count = 1 THEN SET out_count = 2;
ELSE RETURN ret;
END CASE;
WHILE out_count > 0 DO BEGIN
BEGIN
DECLARE out_char CHAR(1);
DECLARE base64_getval CURSOR FOR SELECT c FROM core_base64_data WHERE val = (accum_value >> 18);
OPEN base64_getval;
FETCH base64_getval INTO out_char;
CLOSE base64_getval;
SET ret = CONCAT(ret,out_char);
SET out_count = out_count - 1;
SET accum_value = accum_value << 6 & 0xffffff;
END;
END; END WHILE;
CASE
WHEN in_count = 2 THEN SET ret = CONCAT(ret,'=');
WHEN in_count = 1 THEN SET ret = CONCAT(ret,'==');
ELSE BEGIN END;
END CASE;
END; END WHILE;
RETURN ret;
END$$
DELIMITER ;
SELECT `id`,`name`, TO_BASE64(content) FROM `db`.`upload`
그러면 blob 값이 content 컬럼에서 base64 문자열로 변환됩니다.그러면 이 스트링을 원하는 대로 다른 테이블에 삽입할 수 있습니다.
편집: 또는...이것도 있습니다.에휴.
관심 있는 분들을 위해 지금까지의 유일한 대안입니다.
1) 다음 기능 사용:
http://wi-fizzle.com/downloads/base64.sql
2) sys_eval UDF, (Linux)가 이미 있는 경우 다음을 수행할 수 있습니다.
sys_eval(CONCAT("echo '",myField,"' | base64"));
첫 번째 방법은 느린 것으로 알려져 있습니다.두 번째 문제는 인코딩이 실제로 "외부" MySQL에서 발생하고 있다는 것입니다.MySQL은 인코딩에 문제가 있을 수 있습니다(sys_* 함수로 인한 보안 위험 제외).
유감스럽게도 MySQL에는 UDF 컴파일 버전(더 빨라야 함)도 네이티브 지원도 없습니다(Posgresql은 이를 지원합니다!).
MySQL 개발팀은 이 기능이 이미 다른 언어로 존재하기 때문에 구현에 관심이 없는 것 같습니다.저에게는 매우 바보 같은 생각이 듭니다.
지원 테이블이 필요 없는 또 다른 맞춤형 구현:
drop function if exists base64_encode;
create function base64_encode(_data blob)
returns text
begin
declare _alphabet char(64) default 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
declare _lim int unsigned default length(_data);
declare _i int unsigned default 0;
declare _chk3 char(6) default '';
declare _chk3int int default 0;
declare _enc text default '';
while _i < _lim do
set _chk3 = rpad(hex(binary substr(_data, _i + 1, 3)), 6, '0');
set _chk3int = conv(_chk3, 16, 10);
set _enc = concat(
_enc
, substr(_alphabet, ((_chk3int >> 18) & 63) + 1, 1)
, if (_lim-_i > 0, substr(_alphabet, ((_chk3int >> 12) & 63) + 1, 1), '=')
, if (_lim-_i > 1, substr(_alphabet, ((_chk3int >> 6) & 63) + 1, 1), '=')
, if (_lim-_i > 2, substr(_alphabet, ((_chk3int >> 0) & 63) + 1, 1), '=')
);
set _i = _i + 3;
end while;
return _enc;
end;
drop function if exists base64_decode;
create function base64_decode(_enc text)
returns blob
begin
declare _alphabet char(64) default 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
declare _lim int unsigned default 0;
declare _i int unsigned default 0;
declare _chr1byte tinyint default 0;
declare _chk4int int default 0;
declare _chk4int_bits tinyint default 0;
declare _dec blob default '';
declare _rem tinyint default 0;
set _enc = trim(_enc);
set _rem = if(right(_enc, 3) = '===', 3, if(right(_enc, 2) = '==', 2, if(right(_enc, 1) = '=', 1, 0)));
set _lim = length(_enc) - _rem;
while _i < _lim
do
set _chr1byte = locate(substr(_enc, _i + 1, 1), binary _alphabet) - 1;
if (_chr1byte > -1)
then
set _chk4int = (_chk4int << 6) | _chr1byte;
set _chk4int_bits = _chk4int_bits + 6;
if (_chk4int_bits = 24 or _i = _lim-1)
then
if (_i = _lim-1 and _chk4int_bits != 24)
then
set _chk4int = _chk4int << 0;
end if;
set _dec = concat(
_dec
, char((_chk4int >> (_chk4int_bits - 8)) & 0xff)
, if(_chk4int_bits > 8, char((_chk4int >> (_chk4int_bits - 16)) & 0xff), '\0')
, if(_chk4int_bits > 16, char((_chk4int >> (_chk4int_bits - 24)) & 0xff), '\0')
);
set _chk4int = 0;
set _chk4int_bits = 0;
end if;
end if;
set _i = _i + 1;
end while;
return substr(_dec, 1, length(_dec) - _rem);
end;
디코딩 후 문자 집합을 변환해야 합니다.convert(base64_decode(base64_encode('ёлка')) using utf8)
이것이 5.6 미만에서 필요한 경우, 정상적으로 동작하고 있는 것처럼 보이는 UDF에 걸려 넘어졌습니다.
https://github.com/y-ken/mysql-udf-base64
create table encrypt(varchar(20), password varbinary(200)
암호화 값 "raju", "crypt_crypt_cryptar" 'key' )에 username='raju'; 에서 *,cast(crypt_crypt(password,'key')를 char(40)로 선택합니다.
언급URL : https://stackoverflow.com/questions/358500/base64-encode-in-mysql
'programing' 카테고리의 다른 글
j쿼리 수 하위 요소 (0) | 2023.01.01 |
---|---|
PHP로 GET 변수를 제거하는 아름다운 방법? (0) | 2023.01.01 |
'create_date' 타임스탬프 필드의 기본값이 잘못되었습니다. (0) | 2023.01.01 |
PEP8의 E128: 시각적 들여쓰기를 위한 언더인디드 연속선이란 무엇입니까? (0) | 2023.01.01 |
jQuery Datepicker 텍스트 상자에 오늘 날짜를 미리 입력하려면 어떻게 해야 합니까? (0) | 2023.01.01 |