为什么MariaDB数据库中有两行违反唯一约束?

huangapple go评论62阅读模式
英文:

Why are there are two rows in MariaDB database violating unique constraint?

问题

我已经用JavaScript编写了一个应用程序,通过与MariaDB服务器的连接将数据插入两个表中。

第一次运行应用程序时,这两个表之间应该是一对一的对应关系。

一个表存储有关属性的(模拟)数据,另一个表存储有关价格的数据。每个属性应该有一个价格。在以后的日期,价格可能会更改,所以可能会有多个价格条目,但在首次运行应用程序时不能发生这种情况。这些条目也不能违反唯一索引的规定 - 但它们违反了。

也许我在MariaDB中配置错了一些东西?以下是生成表的代码。

drop table if exists property_price;
drop table if exists property;

create table property
(
  unique_id bigint unsigned not null auto_increment primary key,
  web_id bigint unsigned not null,
  url varchar(256),
  street_address varchar(256),
  address_country varchar(64),
  property_type varchar(64),
  num_bedrooms int,
  num_bathrooms int,
  created_datetime datetime not null,
  modified_datetime datetime not null
);

create table property_price
(
  property_unique_id bigint unsigned not null,
  price_value decimal(19,2) not null,
  price_currency varchar(64) not null,
  price_qualifier varchar(64),
  added_reduced_ind varchar(64),
  added_reduced_date date,
  created_datetime datetime not null
);

alter table property_price
add constraint fk_property_unique_id foreign key(property_unique_id)
references property(unique_id);

alter table property
add constraint ui_property_web_id
unique (web_id);

alter table property
add constraint ui_url
unique (url);

alter table property_price
add constraint ui_property_price
unique (property_unique_id, price_value, price_currency, price_qualifier, added_reduced_ind, added_reduced_date);

下面是DBeaver的截图,显示选择语句返回两行相同的数据。

我不明白为什么唯一约束似乎被违反。约束有时候会起作用,因为如果我再次运行我的应用程序,它会失败,因为它尝试插入数据库中已经存在的重复行(不同于下面显示的行)。

有人能指导我如何调试这个问题吗?

为什么MariaDB数据库中有两行违反唯一约束?

英文:

I have written an application in Javascript which inserts data into two tables via a connection to a MariaDB server.

There should be a 1:1 correspondance between the rows in these tables when first running the application.

One table stores (simulated) data about properties, the other table stores data about prices. There should be 1 price for each property. At a later date, the price might change, so there could be more than one entry for the price, but this cannot happen when the application is first run. These entries also cannot be in violation of a unique index - but they are.

Perhaps I have misconfigured something in MariaDB? Here is the code which generates the tables.

drop table if exists property_price;
drop table if exists property;

create table property
(
  unique_id bigint unsigned not null auto_increment primary key,
  web_id bigint unsigned not null,
  url varchar(256),
  street_address varchar(256),
  address_country varchar(64),
  property_type varchar(64),
  num_bedrooms int,
  num_bathrooms int,
  created_datetime datetime not null,
  modified_datetime datetime not null
);

create table property_price
(
  property_unique_id bigint unsigned not null,
  price_value decimal(19,2) not null,
  price_currency varchar(64) not null,
  price_qualifier varchar(64),
  added_reduced_ind varchar(64),
  added_reduced_date date,
  created_datetime datetime not null
);

alter table property_price
add constraint fk_property_unique_id foreign key(property_unique_id)
references property(unique_id);

alter table property
add constraint ui_property_web_id
unique (web_id);

alter table property
add constraint ui_url
unique (url);

alter table property_price
add constraint ui_property_price
unique (property_unique_id, price_value, price_currency, price_qualifier, added_reduced_ind, added_reduced_date);

Below is a screenshot from DBeaver showing that a select statement returns two identical rows.

I don't understand why the unique constraint appears to be violated. The constraint does sometimes work, because if I run my application again, it fails because it attempts to insert a duplicate row which already exists in the DB. (Not the same as the one shown below.)

Can anyone point me in the right direction as to how I might debug this?

为什么MariaDB数据库中有两行违反唯一约束?

答案1

得分: 0

NULL值在唯一索引中无法工作。在这两个记录中,price_qualifier是NULL。因此,可能会出现重复记录。

英文:

NULL values ​​in unique indexes do not work. price_qualifier is NULL in both records. Therefore, duplicate records become possible.

答案2

得分: -3

MariaDB允许在唯一约束的一部分列上具有多个值。

我的解决方案是将检查重复行的逻辑放入应用程序中,而不是放在数据库端。基本上,这意味着唯一约束未被使用。

一个替代方法可能是重新设计数据库表的结构,例如将可以为空的列拆分到不同的表中。

在我的情况下,这是不可能的,因为一行代表了在特定时间点获取的数据。因此,MariaDB的设计不适合存储我的特定用例的数据。无法改变这一现实,因此需要在应用程序中添加额外的逻辑。无论有多少负面评价都无法改变这一现实。

如果MariaDB具有一项设置,可以阻止在可为空列上定义唯一索引的行中存在多个空值,那么情况可能会不同。

还有另一种可能的替代方法,但它并不更好。

通过使列“非空”,唯一索引问题消失了,我们无法有重复行。然而,如果要插入一些值为空的数据,那么应用程序端再次需要额外的逻辑来插入一个代表空的虚拟值。

这可能是一个空字符串,但这可能会令人困惑,因此一个特殊的字符串,如<NULL>可能更可取。

然而,这并不能避免在应用程序端需要额外的逻辑的问题。现在,我们需要逻辑来处理插入和数据检索(select),以检查<NULL>,并将其转换为与用于与数据库进行接口的语言相关的可为空类型。

英文:

MariaDB permits multiple values on columns which form part of a unique constraint.

My solution would be to put the logic for checking for duplicate rows into the application, rather than this being on the database side. Essentially this means the unique constraint is not being used.

An alternative to this might be to restructure the design of the database tables, for example by factoring out the columns which can be null into a different table.

In my case this is not possible, because one row represents the data that was obtained at a particular point in time. Therefore, it is the case that the design of MariaDB does not lend itself well to storing data for my particular use case. There is nothing that can be done about this, and therefore additional logic is required in the application. No amount of down votes will change this reality.

If MariaDB had a setting to cause prevent multiple null values from being valid within a row where a unique index is defined on nullable columns, then things would be different.


There is another possible alternative, but it isn't much better.

By making the columns not null, the unique index problem goes away, and we cannot have duplicate rows. However, if we have data to insert where some values are null, then additional logic is again required on the application side to insert a dummy value to represent null.

This could perhaps be an empty string, but this might be confusing, so a special string such as <NULL> might be preferable.

However, this does not avoid the problem of requiring additional logic on the application side. We would now need logic for both insertion and data retrival (select), which checks for <NULL>, and converts this to some nullable type for whichever language is being used to interface with the database.

huangapple
  • 本文由 发表于 2023年2月19日 18:29:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75499463.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定