MySQL MySQL中的base64编码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/358500/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 12:29:37  来源:igfitidea点击:

base64 encode in MySQL

mysqlbase64

提问by BCS

I want to select a blob col from one table, base64 encode it and insert it into another tables. Is there any way to do this without round tripping the data out of the DB and through my app?

我想从一个表中选择一个 blob col,base64 对其进行编码并将其插入到另一个表中。有没有办法做到这一点,而无需将数据从数据库和我的应用程序中往返?

回答by pau.moreno

I was looking for the same thing and I've just seen that MySQL 5.6 has a couple of new string functions supporting this functionality: TO_BASE64and FROM_BASE64.

我一直在寻找同样的东西,我刚刚看到 MySQL 5.6 有几个支持此功能的新字符串函数:TO_BASE64FROM_BASE64

回答by WOLFF

Functions from http://wi-fizzle.com/downloads/base64.sqlcontain some error when in encoded string are 32-byte (space), ex BASE64_ENCODE(CONCAT(CHAR(15), CHAR(32))). Here is corrected function

当编码字符串为 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 ;

回答by Pini Cheyni

SELECT `id`,`name`, TO_BASE64(content) FROM `db`.`upload`

this will convert the blob value from contentcolumn to base64 string. Then you can do with this string whatever you want even insert it into another table

这会将 blob 值从内容列转换为 base64 字符串。然后你可以用这个字符串做任何你想做的事情,甚至将它插入到另一个表中

回答by ieure

Looks like no, though it was requested, and there's a UDF for it.

看起来没有,尽管它是被请求的,而且有一个 UDF。

Edit: Or there's… this. Ugh.

编辑:或者有……这个。啊。

回答by lepe

For those interested, these are the only alternatives so far:

对于那些感兴趣的人,这些是迄今为止唯一的选择:

1) Using these Functions:

1) 使用这些功能:

http://wi-fizzle.com/downloads/base64.sql

http://wi-fizzle.com/downloads/base64.sql

2) If you already have the sys_eval UDF, (Linux) you can do this:

2)如果你已经有了sys_eval UDF,(Linux)你可以这样做:

sys_eval(CONCAT("echo '",myField,"' | base64"));

The first method is known to be slow. The problem with the second one, is that the encoding is actually happening "outside" MySQL, which can have encoding problems (besides the security risks that you are adding with sys_* functions).

众所周知,第一种方法很慢。第二个的问题是编码实际上是在“外部”MySQL 中发生的,这可能存在编码问题(除了您使用 sys_* 函数添加的安全风险之外)。

Unfortunately there is no UDF compiled version (which should be faster) nor a native support in MySQL (Posgresql supports it!).

不幸的是,没有 UDF 编译版本(应该更快),也没有 MySQL 中的本机支持(Posgresql 支持它!)。

It seems that the MySQL development team are not interested in implement itas this function already exists in other languages, which seems pretty silly to me.

MySQL 开发团队似乎对实现它不感兴趣,因为这个功能已经存在于其他语言中,这对我来说似乎很愚蠢。

回答by Bars

Yet another custom implementation that doesn't require support table:

另一个不需要支持表的自定义实现:

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), '##代码##')
                    , if(_chk4int_bits > 16, char((_chk4int >> (_chk4int_bits - 24)) & 0xff), '##代码##')
                );
                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;

Gist

要旨

You should convert charset after decoding: convert(base64_decode(base64_encode('ёлка')) using utf8)

您应该在解码后转换字符集: convert(base64_decode(base64_encode('ёлка')) using utf8)

回答by Kevin McFadden

If you need this for < 5.6, I tripped across this UDF which seems to work fine:

如果您在 < 5.6 中需要这个,我会遇到这个似乎工作正常的 UDF:

https://github.com/y-ken/mysql-udf-base64

https://github.com/y-ken/mysql-udf-base64

回答by user9828512

create table encrypt(username varchar(20),password varbinary(200))

创建表加密(用户名 varchar(20),密码 varbinary(200))

insert into encrypt values('raju',aes_encrypt('kumar','key')) select *,cast(aes_decrypt(password,'key') as char(40)) from encrypt where username='raju';

insert into encrypt values('raju',aes_encrypt('kumar','key')) select *,cast(aes_decrypt(password,'key') as char(40)) from encrypt where username='raju';