MySQL表名中的UTF-8补充字符?

MySQL表名中的UTF-8补充字符?,mysql,utf-8,Mysql,Utf 8,我在做什么 我正在开发一个聊天应用程序(用PHP编写),它允许用户创建自己的聊天室。用户可以随意命名聊天室,这个名称将在一个准备好的语句中作为相应聊天室的表名传递给MySQL数据库 可以理解的是,该应用程序没有登录/安全措施,保存聊天日志的表由记录组成,记录仅包含用户提交的文本和时间戳(2列,不计算自动增量主键) 我所面临的 考虑到这个应用程序的简单性质,我无意改变数据库的结构,但我现在遇到了一个问题,即用户输入表情符号(或其他补充字符)作为自己聊天室的名称。根据MySQL内部的工作方式,将这些

我在做什么

我正在开发一个聊天应用程序(用PHP编写),它允许用户创建自己的聊天室。用户可以随意命名聊天室,这个名称将在一个准备好的语句中作为相应聊天室的表名传递给MySQL数据库

可以理解的是,该应用程序没有登录/安全措施,保存聊天日志的表由记录组成,记录仅包含用户提交的文本和时间戳(2列,不计算
自动增量
主键)

我所面临的

考虑到这个应用程序的简单性质,我无意改变数据库的结构,但我现在遇到了一个问题,即用户输入表情符号(或其他补充字符)作为自己聊天室的名称。根据MySQL内部的工作方式,将这些信息按原样传递到数据库会将字符转换为问号():

标识符在内部转换为Unicode。[…]带引号或不带引号的标识符中不允许使用ASCII NUL(U+0000)和补充字符(U+10000及以上)。

我应该/可以做些什么来避免这个问题?在这种情况下,是否有“转义”/“消毒”用户输入的最佳实践?我将各个单词用引号括起来,因为我知道这不是处理数据库中用户输入的正确/典型方式

我正在尝试的


我的一个想法是使用
rawurlencode()
将补充字符分解成独特的序列,我可以将这些序列传递到数据库,并且仍然可以确保使用名为
的聊天室动态创建的表(无论它们的命名方案如何)很少是明智的设计选择。它们使您编写的每个查询都变得更加复杂,并且消除了SQL作为一种语言和关系数据库作为一个概念的大部分用处

此外,允许用户直接选择表名听起来像是一场即将发生的安全灾难。准备好的语句不会以任何方式保存您,因为表名被视为查询的一部分,而不是数据的一部分

除非您对这种不同寻常的设计有非常令人信服的理由,否则我强烈建议更改为拥有一个包含
聊天室日志的单一表,其中包含一列
聊天室id
,该列引用了
聊天室
表。然后,
chat_rooms
表可以包含名称,该名称可以包含用户想要的任何字符,以及关于聊天室创建日期、描述、附加功能等的附加数据。这种方法只需要两个表,但是创建了许多聊天室


如果您真的认为每个聊天室都需要一个单独的表,因为您正试图进行一些巧妙的分区/分片,我仍然建议您使用一个
聊天室
表,然后您可以简单地以
聊天室id
命名这些表,例如
聊天室日志1
聊天室日志2
,等等。这种方法需要比当前方法多出一个表,即num_tables=num_chat_rooms+1。

动态创建的表,无论其命名方案如何,很少是明智的设计选择。它们使您编写的每个查询都变得更加复杂,并且消除了SQL作为一种语言和关系数据库作为一个概念的大部分用处

此外,允许用户直接选择表名听起来像是一场即将发生的安全灾难。准备好的语句不会以任何方式保存您,因为表名被视为查询的一部分,而不是数据的一部分

除非您对这种不同寻常的设计有非常令人信服的理由,否则我强烈建议更改为拥有一个包含
聊天室日志的单一表,其中包含一列
聊天室id
,该列引用了
聊天室
表。然后,
chat_rooms
表可以包含名称,该名称可以包含用户想要的任何字符,以及关于聊天室创建日期、描述、附加功能等的附加数据。这种方法只需要两个表,但是创建了许多聊天室


如果您真的认为每个聊天室都需要一个单独的表,因为您正试图进行一些巧妙的分区/分片,我仍然建议您使用一个
聊天室
表,然后您可以简单地以
聊天室id
命名这些表,例如
聊天室日志1
聊天室日志2
,等等。这种方法需要比当前方法多出一个表,即num_tables=num_chat_rooms+1。MySQL需要端到端的字符集utf8mb4来存储表情符号和一些汉字

在中,您将找到有关“最佳实践”的更多信息,以及当您未能遵循最佳实践时的调试提示。它不仅是列字符集,也是客户机的字符集

不要使用任何编码/解码例程;这只会让事情变得更糟

最好将实际字符放在MySQL表中,而不是像
U+1F914
\u1F914
等Unicode字符串


为了存储表情符号和一些汉字,MySQL需要端到端的字符集utf8mb4

在中,您将找到有关“最佳实践”的更多信息,以及当您未能遵循最佳实践时的调试提示。它不仅是列字符集,也是客户机的字符集

不要使用任何编码/解码例程;这只会让事情变得更糟

最好将实际字符放在MySQL表中,而不是像
U+1F914
\u1F914
等Unicode字符串


返回到它所在的绘图板。感谢您富有洞察力的回复!回到绘图板上。比