【问题标题】:Creating a struct type as a column value for T-SQL?创建一个结构类型作为 T-SQL 的列值?
【发布时间】:2016-11-11 01:49:27
【问题描述】:

我正在为我的游戏创建一个数据库,我需要存储很多 c 风格的结构。

struct stats{
    int strength, stamina, agility, intelligence, etc..;
}

我一直在研究如何在 t-sql 中创建用户定义的数据类型,MSDN 明确指出用户定义的数据类型不能用作列类型:

A user-defined table type cannot be used as a column in a table or a field in a structured user-defined type.

那里没有变通方法或其他方法来创建基于结构的系统吗?我还需要一个技能结构,我有大约 120 多种技能需要存储在我的玩家表下。我想要的表看起来像这样:

CREATE TABLE [dbo].[Player](
    player_name nvarchar (20),
    gold int,
    player_stats stats,                 // array of 4 ints
    player_skills skills,               // array of 120+ tinyints
    player_location location,           // array of 3 floats (x,y,z)
    player_customization customization, // array of 20+ tinyints
    player_equipment equipment,         // array of 8 ints
    etc....)

有没有一种简单的方法可以做到这一点,还是我只需要将所有这些添加为单独的列类型?感谢您的帮助。

【问题讨论】:

  • 这不是很规范。您应该考虑将其分成单独的列。
  • 通常,您希望为每个结构定义一个表,其中的列与结构中的每个字段对齐。

标签: sql-server tsql


【解决方案1】:

除了 Gordon 的其他建议:

  1. Player 表创建一个不是VARCHAR 的主键。 VARCHAR 列不是一个好的主键;更好的键类型是INT(如果您期望超过 2^31-1 个玩家,则为 BIGINT ;))。与使用字符串的键查找相比,使用整数的键查找更快。还要考虑到您必须在其他表(明细表)中通过他们的主键来引用玩家。

    最简单的方法是让 SQL Server 为您创建这样的整数键。您可以通过将IDENTITY 列添加到表中来执行此操作,并将该列设置为主键。在这种情况下,每次插入播放器表时,都会为播放器分配一个键。您必须在表格中为player_name 列添加一个INDEX,但在某些时候您必须通过他们的名字查找玩家。

    例如:

    CREATE TABLE player(
        player_id INT IDENTITY(1,1) NOT NULL,
        player_name NVARCHAR(128),
        -- ... other columns
        CONSTRAINT PK_player PRIMARY KEY CLUSTERED (player_id)
    );
    
    CREATE INDEX
        IX_player_name
    ON
        player(player_name);
    
  2. 正如 Gordon 已经指出的那样,结构或结构数组不能存储在表中。设计表格的一个好方法是为玩家的每个逻辑分组的数据集创建一个链接到玩家表格的(详细)表格。关系数据库使用列越少越好。

    对于一组不会像player_location 一样更改的信息(结构),您可以争辩将此信息直接存储在播放器表中(列XYZ)。更好的是在单独的表player_location 中包含逻辑分组的信息集。然后,您将在播放器表和位置表之间建立 1:1 的关系。

    CREATE TABLE player_location(
        player_id INT NOT NULL,
        x FLOAT NOT NULL,
        y FLOAT NOT NULL,
        z FLOAT NOT NULL,
        CONSTRAINT PK_player_location PRIMARY KEY CLUSTERED (player_id)
        CONSTRAINT FK_player_location FOREIGN KEY(player_id) REFERENCES player(player_id)
    );
    

    player_equipment 等其他信息组将不断增长,因为我假设玩家在玩游戏时会拿起装备。另一个方面是,随着游戏的发展,你可能会添加新设备(通过模组说)。假设您现在有 100 种设备,但在您的扩展中,您将添加 100 种新设备。假设您接受之前的建议,创建一个包含 100 列的表,然后当您发布 mod 时,您必须添加 100 个新列。

    在一个表中有这么多列本身就是一个坏主意,而且你在发布模组时必须更改设备表。这种思维方式的另一个方面是,您必须存储 100 个(或 mod 之后的 200 个)数据列,这些数据不一定包含任何相关信息。一个玩家可能只有 20 件装备,而您必须存储 100 (200) 列。那会浪费磁盘/内存空间。

    对此进行建模的更好方法是有一个定义表来定义设备和一个玩家-设备表来存储玩家持有的设备。示例:

    CREATE TABLE equipment(
        equipment_id INT NOT NULL,
        equipment_name NVARCHAR(128) NOT NULL,
        -- ...
        CONSTRAINT PK_equipment PRIMARY KEY CLUSTERED (equipment_id)
    );
    
    CREATE TABLE player_equipment(
        player_id INT NOT NULL,
        equipment_id INT NOT NULL,
        amount INT NOT NULL,
        CONSTRAINT PK_player_equipment PRIMARY KEY CLUSTERED (player_id,equipment_id),
        CONSTRAINT FK_player_equipment FOREIGN KEY(player_id) REFERENCES player(player_id),
        CONSTRAINT FK_equipment FOREIGN KEY(equipment_id) REFERENCES equipment(equipment_id)
    );
    

    当你发布一个新模组时,你会在equipment 表中添加新设备,当玩家拿起新装备时,你会在player_equipment 表中添加一行,通过其 ID 引用设备。

无论如何,这些都是您需要深入研究的一些想法。一个好的数据库模型将允许您以更简单的方式(不太复杂)进行写入查询,并允许数据库消耗更少的内存和磁盘空间。

【讨论】:

    【解决方案2】:

    这是你的桌子:

    CREATE TABLE [dbo].[Players](
        player_name nvarchar (20),
        gold int,
        player_stats stats,                 // array of 4 ints
        player_skills skills,               // array of 120+ tinyints
        player_location location,           // array of 3 floats (x,y,z)
        player_customization customization, // array of 20+ tinyints
        player_equipment equipment,         // array of 8 ints
        etc....
    )
    

    这表明您应该有几个其他的表和列:

    • Player_SkillsSkills:每个玩家和每个技能一行,也许还有一个技能等级列。
    • Location:每个位置一行,包含有关位置的信息。 LocationId 将在 Players 表中。
    • Player_EquipmentEquipment:每个玩家和每个设备一排。

    我不知道player_statsplayer_customization 是什么。也许它们只是适合Players 的列;也许他们应该是他们自己的桌子。

    您在“结构”等编程结构方面考虑关系数据库是不合适的。

    【讨论】:

      猜你喜欢
      • 2015-08-21
      • 1970-01-01
      • 2015-08-12
      • 1970-01-01
      • 1970-01-01
      • 2021-03-26
      • 1970-01-01
      • 1970-01-01
      • 2017-06-07
      相关资源
      最近更新 更多