2016-11-11 58 views
1

我正在为我的游戏制作一个数据库,我需要存储很多c风格的结构。为T-SQL创建一个结构类型作为列值?

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....) 

是否有这样做的一个简单的方法还是我只需要添加所有这些作为单独的列类型?谢谢您的帮助。

+1

这是不是很规范化。你应该考虑把它分成不同的列。 –

+0

通常,您需要为每个结构定义一个表,其中的列与结构中的每个字段对齐。 –

回答

1

这是你的表:

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

几个除了戈登的其他建议:

  1. 作出的Player表不是一个VARCHAR主键。 A 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. 正如戈登已经指出的,结构的结构或阵列不能被存储在表中作为这样。设计表格的好方法是为每个玩家分配一组逻辑数据,创建一个链接到玩家表格的(详细)表格。关系数据库对于列数尽可能少的表格更容易。

    的一组信息(结构),不象player_location你可能会说,直接在播放器表存储该信息(列XYZ)改变。更好的做法是将这些逻辑分组的信息集合在一个单独的表中player_location。然后,玩家表格和位置表格之间会有1:1的关系。的信息,如player_equipment

    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)列。这将浪费磁盘/内存空间。

    一个更好的建模方法是定义一个定义表,该表定义了设备和玩家设备表,该表存储玩家持有的设备。例如:

    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) 
    ); 
    

    当你发布一个新的MOD,你会在equipment表中添加新的设备,当玩家拿起新的厂房设备将添加一行到player_equipment表通过其ID引用设备。

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