为什么 JSON 列不能是唯一键?

2024-01-06

我有一个表,里面有一个名为ColumnName该列的数据类型是JSON,我正在努力让它成为unique key,但这是不可能的,我收到了这条消息:

#3152 - JSON 列“columnName”不能在键规范中使用。

我想了解为什么我不能将该列设为唯一键。 请留下讨论此问题的官方文档。

谢谢。


问题更新于 2022 年 11 月 28 日:

我将解释为什么需要将 JSON 列标记为唯一键的实际用法。

在我的 Android 应用程序中,我使用 OTP(一次性密码),它有四种用途:

- 第一次使用,当用户想要登录他的帐户时:

有一个字段和一个按钮。用户将在字段中输入他的电子邮件,然后按按钮继续。

在 MySQL 中,我将检查用户表中是否存在电子邮件。如果电子邮件存在,我会将代码发送到他的电子邮件(4 位数字)并返回{"REQUEST_STATUS": 100}给用户。不然我就回来{"REQUEST_STATUS": 740}给用户。

在我的 Android 应用程序中,如果REQUEST_STATUS was 100,我会将用户导航到验证页面以继续该过程,但如果REQUEST_STATUS was 740,我会告诉用户输入的电子邮件不存在。

- 第二种用法,当用户想要创建一个新帐户时:

有两个字段和一个按钮。用户将在第一个字段中输入他的姓名,在第二个字段中输入他的电子邮件,然后按按钮继续。

在 MySQL 中,我将检查用户表中是否存在电子邮件。如果电子邮件不存在,我会将代码发送到他的电子邮件(4 位数字)并返回{"REQUEST_STATUS": 100}给用户。不然我就回来{"REQUEST_STATUS": 813}给用户。

在我的 Android 应用程序中,如果REQUEST_STATUS was 100,我会将用户导航到验证页面以继续该过程,但如果REQUEST_STATUS was 813,我会告诉用户输入的电子邮件已经存在。

- 第三种用法,当用户想要更改他的电子邮件时:

有一个字段和一个按钮。用户将在字段中输入新电子邮件,然后按按钮继续。

在 MySQL 中,我将检查用户表中是否存在电子邮件。如果该电子邮件不存在,我会将代码发送到他的新电子邮件(4 位数字)并返回{"REQUEST_STATUS": 100}给用户。不然我就回来{"REQUEST_STATUS": 813}给用户。

在我的 Android 应用程序中,如果REQUEST_STATUS was 100,我会将用户导航到验证页面以继续该过程,但如果REQUEST_STATUS was 813,我会告诉用户输入的新电子邮件已经存在。

- 第四种用法,当用户想要删除他的帐户时:

有一个名为“删除我的帐户”的按钮,用户将按该按钮继续。

我会将代码发送到他的电子邮件(4 位数字)并返回{"REQUEST_STATUS": 100}给用户。

在我的 Android 应用程序中,如果REQUEST_STATUS was 100,我会将用户导航到验证页面以继续该过程。


所有发送到电子邮件的代码我都会将其存储在代码表中,该表如下所示:

CREATE TABLE CODES (
    CODE CHAR(4) COLLATE UTF8_UNICODE_CI NOT NULL,
    EMAIL CHAR(200) COLLATE UTF8_UNICODE_CI NOT NULL,
    EXPIRATION_DATE DATETIME NOT NULL, -- Every code will be valid for 10 minutes only.
    NAME CHAR(25) COLLATE UTF8_UNICODE_CI NULL,
    NEW_EMAIL char(200) COLLATE UTF8_UNICODE_CI NULL,
    REMAINING_ATTEMPTS TINYINT(4) NOT NULL, -- Every code has 5 attempts only.
    TYPE TINYINT(4) NOT NULL
) ENGINE = INNODB DEFAULT CHARSET = UTF8 COLLATE = UTF8_UNICODE_CI;

ALTER TABLE CODES ADD UNIQUE KEY (EMAIL,TYPE);

类型列仅保存 1 到 4 之间的值。

如果用户想要登录,则类型列的值为1,2用于创建新帐户,3用于更改电子邮件,4用于删除帐户。

如果类型列的值为 1、3 或 4,则名称列将为空;如果类型列的值为 1、2 或 4,则 new_email 列将为空。

我不会说我喜欢这样设计表格,所以我将表格设计更改为:

CREATE TABLE CODES (
    CODE CHAR(4) COLLATE UTF8_UNICODE_CI NOT NULL,
    EMAIL CHAR(200) COLLATE UTF8_UNICODE_CI NOT NULL,
    EXPIRATION_DATE DATETIME NOT NULL, -- Every code will be valid for 10 minutes only.
    REMAINING_ATTEMPTS TINYINT(4) NOT NULL, -- Every code has 5 attempts only.
    TYPE JSON NOT NULL -- It will look like this {"TYPE": 1} OR {"TYPE": 2, "NAME": "..."} OR {"TYPE": 3, "NEW_EMAIL": "..."} OR {"TYPE": 4}
) ENGINE = INNODB DEFAULT CHARSET = UTF8 COLLATE = UTF8_UNICODE_CI;

现在看起来好多了,但我无法将电子邮件和类型列设置为唯一键。

根据下面比尔·卡文的回答,我读到对生成的列进行索引以提供 JSON 列索引 https://dev.mysql.com/doc/refman/8.0/en/create-table-secondary-indexes.html#json-column-indirect-index,我明白了我该怎么做。

但这种方式的问题是我需要创建一个额外的列来从 JSON 内的字段中获取值。

是否可以使 JSON 中的电子邮件列和类型字段成为唯一键,而无需创建额外的列?


这在一个非常明显的手册页上进行了解释 - JSON 数据类型的页面:

https://dev.mysql.com/doc/refman/8.0/en/json.html https://dev.mysql.com/doc/refman/8.0/en/json.html

JSON 列与其他二进制类型的列一样,不会直接建立索引;相反,您可以在生成的列上创建索引,从 JSON 列中提取标量值。看对生成的列进行索引以提供 JSON 列索引 https://dev.mysql.com/doc/refman/8.0/en/create-table-secondary-indexes.html#json-column-indirect-index,查看详细示例。

您可以对从 JSON 文档提取的标量值创建唯一索引,但无法对整个 JSON 文档创建索引。

TEXT 和 BLOB 也是如此。原因是这些长数据类型对于索引来说太大了。索引中的每个单个条目必须适合一个数据库页面,但 JSON、TEXT 和 BLOB 可能跨越许多页面。


回复您的更新:

在 MySQL 8.0 中,您可以在表达式上创建索引,而无需创建中间虚拟列。如果您使用MySQL 5.7,则需要升级才能获得此功能。

Demo:

mysql> ALTER TABLE CODES ADD UNIQUE KEY (EMAIL, (CAST(TYPE->>'$.TYPE' AS UNSIGNED)));

mysql> insert into CODES values ('blah', '[email protected] /cdn-cgi/l/email-protection', now(), 0, '{"TYPE":1}');
Query OK, 1 row affected (0.01 sec)

mysql> insert into CODES values ('blah', '[email protected] /cdn-cgi/l/email-protection', now(), 0, '{"TYPE":1}');
ERROR 1062 (23000): Duplicate entry '[email protected] /cdn-cgi/l/email-protection' for key 'codes.functional_index'

mysql> insert into CODES values ('blah', '[email protected] /cdn-cgi/l/email-protection', now(), 0, '{"TYPE":2}');
Query OK, 1 row affected (0.00 sec)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 JSON 列不能是唯一键? 的相关文章

  • 为什么我的 if 语句没有按我预期的方式工作?

    我正在尝试实现以下目标 我向我的 SQL 数据库询问使用SELECT FROM subjects 这样做之后我要求使用数组mysqli fetch assoc 在那之前一切都很好 现在的问题是 当我尝试在每个循环中修改 genero 的值
  • 是否有适用于所有数据库的标准sql

    如下所示 不同数据库的语法有所不同 是否存在适用于所有数据库的标准方法 有没有什么工具可以将任意sql转换为任意sql SQL Server 2005 CREATE TABLE Table01 Field01 int primary key
  • 如何从 PostgreSQL 中的时间戳列值提取一天中的时间(或小时)?

    我正在尝试从 PostgreSQL 中的 时间戳 列中提取一天中的时间 这是我的做法 但是 太糟糕了 知道如何做得更好吗 SELECT date part hour date demande text hours date part min
  • MySQL 查询计算上个月

    我想计算上个月的订单总额 我收到了从当前日期获取当月数据的查询 SELECT SUM goods total AS Total Amount FROM orders WHERE order placed date gt date sub c
  • 如何使用 vitess 仅对特定表进行分片

    我创建了一个包含三个表的未分片键空间 现在我想对前两个表的键空间进行分片 但不想对第三个表进行分片 如何才能做到这一点 Vitess 文档不包含任何与此相关的信息或示例 请帮忙 Thanks vitess 中的垂直分片与水平分片类似 您应该
  • 即使使用“autoReconnect=true”,MySql JDBC 也会超时[重复]

    这个问题在这里已经有答案了 有时 我的 Java Tomcat6 Debian Squeeze 应用程序无法与 MySql 服务器通信 Tomcat 应用程序位于前端服务器上 而 MySql 位于单独的 仅限 MySql 的机器上 一个典型
  • 跨多个表进行搜索,并在结果行中显示表名称

    如何构建 SQL 语句以跨多个平面不相关的表运行 并使用选择结果和结果来自的表的名称显示结果 这种情况是这样的 我有几个表 每个表都有相同的列名 这是我从外部各方收到的数据 并将其存储在不同的表中 相同的表看起来像 Table 1 pid
  • 如何将ElasticSearch与MySQL集成?

    在我的一个项目中 我计划将 ElasticSearch 与 MySQL 结合使用 我已经成功安装ElasticSearch 我可以单独管理ES中的索引 但我不知道如何用 MySQL 实现同样的功能 我读过一些文件 但我有点困惑 没有明确的想
  • 使用 ADODB 连接从关闭的工作簿中检索数据。某些数据被跳过?

    我目前正在编写一些代码 可以通过 ADODB 连接访问单独的工作簿 由于速度的原因 我选择了这种方法而不是其他方法 下面是我的代码 Sub GetWorksheetData strSourceFile As String strSQL As
  • 如何 md5 所有列(无论类型如何)

    我想创建一个 sql 查询 或 plpgsql 它将 md5 所有给定的行 无论类型如何 但是 在下面 如果 1 为空 则哈希为空 UPDATE thetable SET hash md5 accountid accounttype cre
  • PDO PHP 连接,致命错误

    我的连接类 firstcode php class DB functions public db function construct try db new PDO mysql localhost dbname xxx charset ut
  • 如何使用 Perl 更改 mysql 密码

    我需要使用 Perl 脚本更改一些 mysql 密码 以下内容在更改数据库条目时有效 但是当我针对 mysql 用户更改修改它时 它将它们重置为空白密码 最后 刷新权限 也很好 但我还没有找到方法 usr bin perl use DBI
  • 为什么我可以像调用实例方法一样调用类方法?

    我正在查看这个例子 class SQLObject def self columns return columns if columns columns DBConnection execute2 lt lt SQL first SELEC
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • 计算运行总计时出错(之前期间的累计)

    我有一张桌子 我们称之为My Table有一个Created日期时间列 在 SQL Server 中 我试图提取一个报告 该报告显示历史上有多少行My Table按月在特定时间 现在我知道我可以显示有多少added每个月 SELECT YE
  • 如何使用sql作为xml路径('')但保留回车符

    我有下面的代码 select select cast Narrative as Varchar max char 13 from officeclientledger where ptmatter matter and ptTrans 4
  • 如何从shell脚本自动登录MySQL?

    我有一个 MySQL 服务器 其中有一个用户和密码 我想在 shell 脚本中执行一些 SQL 查询而不指定密码 如下所示 config sh MYSQL ROOT root MYSQL PASS password mysql sh sou
  • 如何在NiFi中映射流文件中的列数据?

    我有 csv 文件 其结构如下 Alfreds Centro Ernst Island Bacchus Germany Mexico Austria UK Canada 01 02 03 04 05 现在我必须将这些数据移入数据库 如下所示
  • 如何获得顶部带有千位分隔符的数字?

    SELECT count FROM table A 假设结果是8689 我怎样才能将它转换为8 689在 SQL Server 上 尝试这样 select replace convert varchar convert Money coun
  • MS ACCESS 计数/求和行数,不重复

    我有下表 我需要计算总行数而不包括任何重复记录 CustomerID test1 test1 test2 test3 test4 test4 如您所见 总行数为 6 但有两个 test1 和两个 test4 我希望查询返回 4 IOW 我想

随机推荐

  • 如何在控制台应用程序中设置默认连接字符串?

    在我的带有 Web 界面的 MVC 项目中 我习惯在 Web Config 文件中设置连接字符串 但是 现在我正在制作一个沼泽标准控制台应用程序 也带有数据库挂钩 但如何为应用程序全局设置连接字符串 目前 我正在设置 var dbIndex
  • 当为结构体分配 null 值时,CLR 如何绕过抛出错误?

    我试图理解这段代码中的一件事 Nullable
  • 从 Azure 连接到 HTTPS Web 服务

    我在 Azure 中有一个 Web 角色 必须连接到受 SSL 保护的外部 Web 服务 当应用程序尝试连接到 Web 服务时 会出现错误 无法建立 SSL TLS 安全通道的信任关系 具有权限 certname organization
  • WMI - 直接访问 Win32_OperatingSystem 的单例实例

    我无法直接访问Win32 操作系统通过 WMI 公开的管理类 它是一个单例类 我非常确定 Win32 OperatingSystem 是获取单例实例的正确路径语法 对 InvokeMethod 的调用会产生问题底部列出的异常 访问 Clas
  • 是否可以使用 Commons Beanutils 自动实例化嵌套属性?

    我在用着PropertyUtils setProperty 对象 名称 值 Apache Commons Beanutils 的方法 开设这些课程 public class A B b public class B C c public c
  • java中如何从字符串中删除一些单词

    我在android平台上工作 我使用一个字符串变量来填充html内容 之后我想删除一些单词 具体来说 删除之间的任何单词 标签 有什么解决办法吗 String newHtml oldHtml replaceFirst s 1 3 解释 ol
  • Excel VBA 自动筛选数组

    我正在使用 Microsoft Excel 的 VBA 中的自动筛选器 我对它如何处理过滤数组有疑问 我已经将原来的上下文淡化为简化版本 最初是为了理解这个问题 在范围 A1 A5 的工作表中 假设我们有Fruit Apple Banana
  • Android WebView 在用户交互之前无法完全渲染内容

    我有一个扩展 WebView 的自定义类 用于显示 HTML 内容 当用户单击 HTML 文档中的链接时 我计算要滚动到的 X 值 然后使用scrollTo x y 通过可运行对象显示该位置 见下文 post new Runnable Ov
  • 一个关于比较List的问题

    我有两个清单 List
  • RabbitMQ - 通道关闭:连接错误(SpringXD 重复关闭rabbitmq 连接。)

    我度过了一个糟糕的夜晚 试图弄清楚 RabbitMQ 和 SpringXD 到底发生了什么 不幸的是没有成功 问题 SpringXD反复关闭RabbitMQ连接 或报告与通道缓存大小相关的警告 SpringXD 日志的片段 在流初始化 自动
  • 猫鼬自定义模式类型

    我从 mongoose 文档中了解到 可以创建自定义模式类型并将其添加到已有的模式类型中 正如所建议的 我尝试研究猫鼬长的例子 https github com aeckmann mongoose long https github com
  • 退格键在 Eclipse Mars 中恢复

    我在 Eclipse Mars 4 5 0 中的退格键的作用类似于删除键 它删除右侧字符而不是左侧字符 这真的很令人困惑 也许我不小心使用了快捷键 我尝试重新启动 Eclipse 但没有成功 我还尝试将键绑定首选项切换为 Emacs 方案
  • 检查页面是父页面还是子页面?

    是否可以检查页面是父页面还是子页面 我的页面设置如下 家长 子页1 子页2 etc 如果它是父页面 我想显示某个菜单 如果它在子页面上 我想显示不同的菜单 我知道我可以做类似下面的事情 但我想让它更加动态 而不包含特定的页面 ID 您可以测
  • “kotlin-noarg”插件在 Realm 中不起作用

    kotlin allopen 插件可以工作 但 kotlin noarg 插件不起作用 我能怎么做 下面是代码 构建 gradle buildscript ext kotlin version 1 1 3 2 repositories go
  • cin 首次使用函数后不允许输入

    对于 C 或任何类型的编程来说都是全新的 我正在尝试进行简单的输入 输出 但是在回答第一个问题后 我没有机会输入第二个输入 我尝试过在网上查找内容 但考虑到这是一个非常简单的代码 据说哈哈 没有人遇到过同样的问题 这让我来到这里 inclu
  • 生产中的高超音速休眠?

    开发商高超音速 http hsqldb org 承诺提高绩效 但我担心使用 hsqlDB 的管理和其他方面会出现问题 有人在生产中使用这个吗 这是个好主意吗 许多公司 http hsqldb org web hsqlUsing html在生
  • 如何评估 WHERE 子句中的输入

    我正在我的一个变量中输入一个输入 基本上我想做一些类似的事情 SELECT FROM PEOPLE WHERE IF INPUT 1 ITEMID 16 OR ITEMID 13 ELSE IF INPUT 2 ITEMID 11 OR I
  • Java SFTP (apache vfs2) - 密码带有@

    我正在尝试使用 org apache commons vfs2 通过 SFTP 下载文件 问题是 密码包含 字符 因此这会导致 URI 被错误解析 org apache commons vfs2 FileSystemException Ex
  • 有没有办法只限制mysql中的较低范围?

    我想获取查询中除第一行之外的所有行 我怎样才能做到这一点 您可以使用大量行 偏移量为1 LIMIT 1 18446744073709551615
  • 为什么 JSON 列不能是唯一键?

    我有一个表 里面有一个名为ColumnName该列的数据类型是JSON 我正在努力让它成为unique key 但这是不可能的 我收到了这条消息 3152 JSON 列 columnName 不能在键规范中使用 我想了解为什么我不能将该列设