如何在sql数据库中创建动态数据字段

时间:2020-09-06 04:41:40

标签: mysql sql sql-server database mongodb

在数据库级别处理动态数据字段出现了一个要求。假设我们有一个名为Employee的表,该表有一个名称,姓氏,并且没有联系字段(3个基本字段)。因此,随着应用程序的进展,要求数据库和应用程序应该能够添加(处理)可以随类型添加到数据库中的动态数据字段。

Ex:用户将动态地将出生数据,地址字段添加到Employee表中,该表主要有3个基本字段。

问题是如何以最佳方式满足这一要求?

我已经设计了一张桌子来满足此需求,但是我愿意采用行业标准的最佳方式来实现这一目标,而不会出现未来的问题

请与此协作。

image: the way I have designed tables

4 个答案:

答案 0 :(得分:1)

基本上,您可以使用四个选项来处理此类动态字段:

  1. 每当添加新列时,修改基表结构。
  2. 使用JSON存储值。
  3. 使用EAV模型(实体属性模型)。
  4. 基本上(1),但将附加值存储在每个用户的单独表或单独表中。

您在问题中没有提供足够的信息来确定哪一个最适合您的数据模型。

但是,这是优点和缺点的快速总结:

用于修改表:不利的一面是,修改表是一项昂贵的操作(尤其是当表变大时)。从正面看,所有用户都可以看到这些列,并且这些列具有适当的类型。

对于JSON:JSON非常灵活。但是,由于每次使用时都会重复每个字段的名称,因此JSON会产生非常大的存储开销。此外,您没有所有添加字段的列表(除非您将其保留在单独的表中)。

对于EAV:EAV是灵活的,但不如JSON灵活。问题在于value列是单个类型(通常是字符串),或者访问数据变得更加复杂。像JSON一样,每次使用时都会重复该值的“名称”。但是,这通常是另一个表的键,因此开销较小。

对于每个用户一个单独的表:这里的主要优点是将用户彼此隔离。如果这是必需的,那么这也许是可行的方法(尽管在EAV模型中添加userId也可以)。

因此,最合适的方法取决于各种因素,例如:

  • 字段将在所有用户之间共享吗?
  • 其他字段是否都具有相同的类型?
  • 您对性能和数据大小有何担忧?
  • 多久添加一次新字段?

答案 1 :(得分:0)

要具有动态字段,可以使用另一个表来设置用户属性

  1. user表中有列
userid, name, surname, contact 

  1. user_props表中有列
propertyid, userid, property, value 

user_props中,您可以插入用户属性,例如

INSERT INTO user_props. (userid, property, value) 
VALUES (1, "date_of_birth", "2010-01-10"),(1, "hobby", "Stackoverflow")

像这样,您可以为用户动态设置任何数字属性。

答案 2 :(得分:0)

使用MongoDB或其他将NoData / Schemaless数据库存储在键=>值对中的数据库可能会更好。对于您事先确定的字段,可以设置类型(在MongoDB中),以便这些列具有模式。对于动态字段,这些字段将存储为字符串,并且您必须以某种方式找出代码中的类型。

如果您需要使用MySQL,则在Employee表中,您可以在自定义字段的第四列-数据库类型json。然后,无论何时添加新的自定义字段,都将添加field_name,field_value和field_type。您的架构可能类似于:

//Schema for Employee table in mysql
id: int
name: varchar
surname: varchar
custom_fields: json //eg { {field_name: DOB, field_value: 06/09/2020, field_type: date},... }

//Schema for contacts table 
id: int
employee_id: int
contact: varchar

在MySQL中,您还可以摆脱custom_fields中的类型(如果可以不使用它的话),并将json构造为简单的key =>值对,这样看起来就像

{
  {"key":"Age","value":"10"},
  {"key":"salary","value":"40,000"},
  {"key":"DOB","value":"06/09/2020"},
}

您似乎在设计hereEntity-Attribute-Value model的一种变体。它可以工作,但是针对这样的模式进行查询将非常麻烦。使用json列更整洁,也更快。最好是使用MongoDB并找出代码中的类型。

答案 3 :(得分:0)

您可以使用包含ALTER DATABASE语句的存储过程来处理这种情况。像这样:

DROP PROCEDURE IF EXISTS set_dynamic_table;
DELIMITER //
CREATE PROCEDURE set_dynamic_table (IN _field_name VARCHAR(50),
                                    IN _field_type VARCHAR(20),
                                    IN _last_field_name varchar(50))
BEGIN
    DECLARE _stmt VARCHAR(1024);
    SET @SQL := CONCAT('ALTER TABLE dynamic_table',
                'ADD COLUMN ' _field_name, field_type, NULL AFTER ,last_field_name);
    PREPARE _stmt FROM @SQL;
    EXECUTE _stmt;
    DEALLOCATE PREPARE _stmt;
END//
DELIMITER;

然后你会