创建结构类型作为T-SQL的列值?

时间:2016-11-11 01:49:27

标签: sql-server tsql

我为我的游戏创建了一个数据库,我需要存储很多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....)

是否有一种简单的方法可以执行此操作,还是只需将所有这些添加为单独的列类型?谢谢你的帮助。

2 个答案:

答案 0 :(得分: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的合适列;也许他们应该是自己的桌子。

您正在考虑编程结构方面的关系数据库,例如"结构"是不合适的。

答案 1 :(得分:2)

除戈登之外还有其他一些建议:

  1. Player表创建一个不是VARCHAR的主键。 VARCHAR列不是一个好的主键;如果您期望超过2 ^ 31-1个玩家,则更好的密钥类型为INT(或BIGINT;))。与使用字符串的键查找相比,使用整数进行键查找更快。还要考虑您必须在其他表(详细信息表)中按主键引用播放器。

    最简单的方法是让SQL Server为您创建这样的整数键。您可以通过向表中添加IDENTITY列来完成此操作,并将该列作为主键。在这种情况下,对于播放器表中的每个插入,将为播放器分配一个键。您必须在INDEX列的表格中添加player_name,但在某些时候您必须按名称查找玩家。

    例如:

    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. 正如戈登已经指出的那样,结构或结构阵列不能存储在表格中。设计表的一种好方法是为播放器的每个逻辑分组的数据集创建一个链接到播放器表的(详细)表。对于具有尽可能少的列的表,关系数据库可以更容易地进行。

    对于一组不像player_location那样改变的信息(结构),您可以争辩将此信息直接存储在播放器表格中(X列,Y和{ {1}})。更好的方法是将这组逻辑分组的信息放在单独的表Z中。然后,您将在播放器表和位置表之间建立1:1的关系。

    player_location

    其他信息组如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) ); 将继续增长,因为我认为玩家将在游戏过程中获取设备。另一个方面是你可能会随着游戏的增长添加新设备(通过mods说)。假设您现在有100种类型的设备,但在您的扩展中,您将添加100种新型设备。假设您采用以前的建议,创建一个包含100列的表,然后当您释放mod时,您将需要添加100个新列。

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

    更好的方法是建立一个定义设备的定义表和一个存储玩家所持设备的玩家设备表。例如:

    player_equipment

    当你发布一个新mod时,你会在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表中添加一行来引用设备的ID

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