`

MYSQL- function 传参 concat 中文乱码

阅读更多

1. 背景

以前使用 postgresql 写存储过程/function 比较多, 这次工作过程中,需要做数据迁移, 将 MYSQL 某些表的数据转成 pgsql数据库中某些表数据

在转换的过程中,需要有以下的转换SQL


if(@birthday is null) then
   @birthday='null';
else    
   @birthday=concat('\'',@birthday,"\'");
end if;

如果 birthday 没有值,那么将使用 'null' 字符串,如果有值,将添加单引号

除了birthday ,我还需要处理

  • @local_real_name
  • @login_mobile
  • @login_name

基于 DRY (Don't repeat youself) 原则, 这里应该写个function

2. 第一版function

于是乎,我就参考了mysql 文档,写了个 function

drop function if exists ifNullElseWithSigleQuotes;

--  -----------------------------------
create function ifNullElseWithSigleQuotes(
    in_string      varchar(255)
)
returns varchar(255)
begin
    declare resultValue varchar(255);

    if(in_string is null) then
       set resultValue='null';
    else    
       set resultValue=concat('\'',in_string,'\'');
    end if;

    return(resultValue);
end

很简洁吧,肉眼看看,没毛病

执行下, 提示:

ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled

(you *might* want to use the less safe log_bin_trust_function_creators variable)

看了下帮助文档


[NOT] DETERMINISTIC:这个是用于binlog和主从复制等!DETERMINISTIC是确定的,
意思就是写入binlog的时候,写入的是一个指定的常量;如unix_timestamp()获取到的值是1,可能写入binlog的时候,unix_timestamp()获取到的时间戳却成了3了,这个时候会出现数据不一致问题,所以引入了DETERMINISTIC!这是binlog安全的一种机制!一般情况下,NOT DETERMINISTIC不允许使用,会报如下错误:
Error CODE : 1418
This FUNCTION has NONE of DETERMINISTIC, NO SQL, OR READS SQL DATA IN its declaration AND BINARY logging IS enabled (you *might* want TO USE the LESS safe log_bin_trust_function_creators variable)

可以从报错内容里面发现,设置log_bin_trust_function_creators函数就可以使用NOT DETERMINISTIC,但是二进制安全性极差!

CONTAINS SQL表示子程序不包含读或写数据的语句;

NO SQL表示子程序不包含SQL语句。

READS SQL DATA表示子程序包含读数据的语句,但不包含写数据的语句。

MODIFIES SQL DATA表示子程序包含写数据的语句。

如果这些特征没有明确给定,默认的是CONTAINS SQL。

我这个function 里面没有sql语句, 那么加上了 no sql

create function ifNullElseWithSigleQuotes(
    in_string      varchar(255)
)
returns varchar(255)
no sql

begin
    declare resultValue varchar(255);

    if(in_string is null) then
       set resultValue='null';
    else    
       set resultValue=concat('\'',in_string,'\'');
    end if;

    return(resultValue);

end

但是依然执行不了

最终解决方案: 找到我们的DBA,将mysql bin-log 参数调整了

参考: http://www.educity.cn/wenda/402115.html

3. 执行

解决了 function创建异常之后, 我们创建function成功,

3.1 test null

select ifNullElseWithSigleQuotes(null);

结果:

ifNullElseWithSigleQuotes(null) |
--------------------------------|
null                            |

没毛病

3.2 test mobile

select ifNullElseWithSigleQuotes('15001841110');

结果:

ifNullElseWithSigleQuotes('15001841110') |
-----------------------------------------|
'15001841110'                            |

也没毛病

3.3 test local_real_name

select ifNullElseWithSigleQuotes('程序员鼓励师');

结果:

SQL 错误 [1366] [HY000]: Incorrect string value: '\xE7\xA8\x8B\xE5\xBA\x8F...' for column 'in_string' at row 1

  java.sql.SQLException: Incorrect string value: '\xE7\xA8\x8B\xE5\xBA\x8F...' for column 'in_string' at row 1

咦,什么情况, 难道是 程序员鼓励师 太美,导致 function 不能执行?

4. 寻找解决方案

第一感觉是乱码, 是不是哪里的编码没有设置,

4.1 找到文档, 加上 charset utf8

drop function if exists ifNullElseWithSigleQuotes;

--  -------------------------------------
create function ifNullElseWithSigleQuotes(
    in_string      varchar(255) charset utf8
)
returns varchar(255) charset utf8
no sql

begin
    declare resultValue varchar(255);

    if(in_string is null) then
       set resultValue='null';
    else    
       set resultValue=concat('\'',in_string,'\'');
    end if;

    return(resultValue);

end

执行:

select ifNullElseWithSigleQuotes('程序员鼓励师');

结果:

SQL 错误 [1366] [HY000]: Incorrect string value: '\xE7\xA8\x8B\xE5\xBA\x8F...' for column 'resultValue' at row 1

java.sql.SQLException: Incorrect string value: '\xE7\xA8\x8B\xE5\xBA\x8F...' for column 'resultValue' at row 1

涛声依旧, 问题依旧

4.2 咨询了下 我们的DBA

DBA启迪了我一个思路, 是不是内部调用的函数有问题, 那么 我修改了一版

drop function if exists ifNullElseWithSigleQuotes;

--  -----------------------------------
create function ifNullElseWithSigleQuotes(
    in_string      varchar(255) charset utf8
)
returns varchar(255) charset utf8
no sql

begin    
    return('111');    
end

执行:

select ifNullElseWithSigleQuotes('程序员鼓励师');

结果:

ifNullElseWithSigleQuotes('程序员鼓励师') |
------------------------------------|
111                                 |

嘿, 是不是很神奇? 看来传参和 return 部分代码没有问题

4.3 concat 的问题?

那就是 concat 有问题了? 找找资料

google 下 mysql concat Incorrect string value

找到了些资料, 但是大部分资料都是说

concat(str1,str2)

当concat结果集出现乱码时,大都是由于连接的字段类型不同导致,如concat中的字段参数一个是varchar类型,一个是int类型或doule类型,就会出现乱码。

解决方法:利用mysql的字符串转换函数CONVERT将参数格式化为char类型就可以了。

举例: concat('数量:',CONVERT(int1,char),CONVERT(int2,char),'金额:',CONVERT(double1,char),CONVERT(double2,char))

但是我的代码

select concat('\'','程序员鼓励师','\'');

结果 :

concat('\'','程序员鼓励师','\'') |
---------------------------|
'程序员鼓励师'                   |

没毛病啊

4.4 柳暗花明

在我没辙的时候, 我看到

 declare resultValue varchar(255);

我给他也加了 charset

代码 :

drop function if exists ifNullElseWithSigleQuotes;

--  ----------------------------
create function ifNullElseWithSigleQuotes(
    in_string      varchar(255) charset utf8
)
returns varchar(255) charset utf8
no sql

begin
    declare resultValue varchar(255) charset utf8;

    if(in_string is null) then
       set resultValue='null';
    else    
       set resultValue=concat('\'',in_string,'\'');
    end if;

    return(resultValue);

end

执行:

select ifNullElseWithSigleQuotes('程序员鼓励师');

结果 :

ifNullElseWithSigleQuotes('程序员鼓励师') |
------------------------------------|
'程序员鼓励师'                            |

5.总结

  • 遇到问题要寻找可能解决的办法(找人问,找资料)
  • 多尝试,多总结
  • 这个小function 我花费了4个小时, 我觉得有必要做个总结,希望如果遇到相同的问题,看了我的这个文章,4分钟就搞定了
  • mysql 想说爱你不容易
1
1
分享到:
评论

相关推荐

    Python库 | flake8-no-implicit-concat-0.2.1.tar.gz

    资源分类:Python库 所属语言:Python 资源全名:flake8-no-implicit-concat-0.2.1.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    前端开源库-source-map-concat

    `source-map-concat`是一个开源库,专门用于处理源映射的合并,使得在进行文件合并时能保持源码映射的准确性。这个库的目标是帮助前端开发者更高效地管理他们的项目,特别是在使用诸如Webpack、Gulp或Grunt等构建...

    nginx中使用nginx-http-concat模块合并静态资源文件

    `concat_max_files`选项限制了最多可合并的文件数量,以防止过大的响应导致问题。 需要注意的是,`nginx-http-concat`并不自动对合并的文件进行压缩或打包,这意味着你需要提前准备好已经压缩过的CSS和JS文件。如果...

    fluent-plugin-concat:Fluentd Filter插件可连接多个事件中分隔的多行日志

    gem 'fluent-plugin-concat' 然后执行: $ bundle 或将其自己安装为: $ gem install fluent-plugin-concat 配置 例子 @type concat key loga #separator "\n" n_lines 10 #multiline_start_regexp /^...

    前端开源库-gulp-concat-css

    gulp.task('concat-css', function() { return gulp.src(['src/css/*.css']) .pipe(concatCss('styles.css')) .pipe(gulp.dest('dist/css')); }); ``` 这段代码将`src/css/`目录下的所有CSS文件合并到`dist/css/...

    前端开源库-stream-concat

    开源库`stream-concat`就是针对这一需求而设计的,它提供了简单且高效的流(Stream)连接功能,特别适合于Node.js环境中处理大文件或者连续数据流。这个库的核心概念是利用流的特性,将多个流串联起来,形成一个连续...

    mysql-function.rar_mysql pdf

    MySQL是一种广泛使用的开源关系型数据库管理系统,以其高效、稳定和易于学习的特点深受开发者喜爱。这份“mysql函数大全(PDF版)”文档无疑是学习和查询MySQL函数的宝贵资源。它涵盖了MySQL中的各种内置函数,包括但...

    前端开源库-fuse-concat-with-sourcemaps

    "fuse-concat-with-sourcemaps"是一个这样的工具,它专注于将多个JavaScript文件合并(concat)在一起,并在此过程中保持源地图(sourcemaps)的完整性。这个开源库的目的是简化前端开发流程,使得在代码压缩、混淆...

    mysql-5.7.30-el7-x86_64.tar.gz

    MySQL 5.7.30 是一个非常重要的版本,它是MySQL数据库系统的一个稳定发行版,专为Linux操作系统(特别是CentOS 7)设计的x86_64架构。这个压缩包“mysql-5.7.30-el7-x86_64.tar.gz”包含了在Linux环境下安装和运行...

    前端开源库-gulp-concat-sourcemap

    gulp.task('concat-js', function () { return gulp.src(['src/js/**/*.js']) .pipe(concat('all.js')) .pipe(gulp.dest('dist/js')); }); // 运行任务 gulp.task('default', ['concat-js']); ``` 在这个例子中...

    mysql-8.0.21-winx64.rar

    MySQL 8.0.21 是一个流行的开源关系型数据库管理系统(RDBMS),由 Oracle 公司维护。这个版本的 MySQL 针对Windows 64位操作系统进行了优化,确保在高性能计算环境下运行良好。MySQL 8.0 系列引入了多项改进和新...

    前端开源库-broccoli-concat-analyser

    **Broccoli-Concat-Analyser:前端开源库的精华解析** 在前端开发中,优化代码组织和性能是至关重要的任务。`Broccoli-Concat-Analyser` 是一个专门用于前端项目构建过程中的代码分析工具,它能帮助开发者理解并...

    前端开源库-fuse-concat-with-sourcemaps.zip

    "fuse-concat-with-sourcemaps" 是一个特定的前端工具,它涉及到了前端构建过程中的两个关键概念:代码合并(concatenation)和源映射(source maps)。这里我们将详细探讨这两个概念以及它们在实际开发中的应用。 ...

    gulp-json-concat::high_voltage:用Gulp将几个JSON文件合并为一个

    -json-CONCAT 结合几个JSON文件与Gulp gulp-json-concat是一个分支,具有一些新选项。 安装 $ npm install --save-dev gulp-json-concat 用法 您可以组合子文件夹中的json文件。 生成的json将删除这些文件夹的名称...

    grunt-cmd-concat:连接 cmd 文件

    grunt-cmd-concat 连接 cmd 文件。入门这个插件需要 Grunt ~0.4.0 如果您以前没有使用过 ,请务必查看指南,因为它解释了如何创建以及安装和使用 Grunt 插件。 熟悉该过程后,您可以使用以下命令安装此插件: npm ...

    grunt-scantree-concat:连接scantree输出中JavaScript文件

    grunt-scantree-concat 连接scantree输出中JavaScript文件什么请参阅了解该过程的工作方式。 在以这种方式设置的项目中, grunt-scantree-concat将scantree输出中列出的文件连接到单个文件中。如何咕unt声这个插件...

    grunt-contrib-concat:连接文件

    grunt-contrib-concat v1.0.1 连接文件。 入门 如果您以前从未使用过 ,请务必查看《指南》,因为它说明了如何创建以及安装和使用Grunt插件。 熟悉该过程后,可以使用以下命令安装此插件: npm install grunt-...

    mysql-centos安装

    SELECT DISTINCT CONCAT('User:\'', user, '\'@\', host, '\'') AS query FROM mysql.user; ``` #### 六、总结 本文详细介绍了如何在CentOS 6及CentOS 7环境下手动安装MySQL的过程,包括清理旧版MySQL、添加依赖...

    SAP-DMS的CONCAT SERVER安装资料

    标题与描述中的关键词"SAP-DMS的CONCAT SERVER安装资料"指向了SAP Content Server的安装指南,这是一份详尽的技术文档,旨在指导用户如何在Windows操作系统上正确安装和配置SAP Content Server,版本为6.30。...

Global site tag (gtag.js) - Google Analytics