Creating a struct type as a column value for T-SQL?

匿名 (未验证) 提交于 2019-12-03 09:19:38

问题:

I'm making a database for my game and I need to store a lot of c style structs.

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

I've been looking at how to create user defined data types in t-sql and MSDN specifically says that user defined data types CANNOT be used as a column type:

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

Is there not a work around, or some other way to create a struct based system in there? I also need a struct for skills and i have around 120+ skills that need to be stored under my player table. My desired table would look something like this:

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

Is there a simple way of doing this or do i just need to add all those as individual column types? Thanks for the help.

回答1:

This is your table:

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

This suggests that you should have several other tables and columns:

  • Player_Skills and Skills: One row per player and per skill, with perhaps a skill level column as well.
  • Location: One row for each location, with information about the location. LocationId would be in the Players table.
  • Player_Equipment and Equipment: One row per player and per equipment.

I don't know what player_stats and player_customization are. Perhaps they are just appropriate columns for Players; perhaps they should be their own tables.

You're thinking of a relational database in terms of programming constructs such as "structures" is not appropriate.



回答2:

Several additional suggestions in addition to Gordon's:

  1. Make a primary key for the Player table that isn't a VARCHAR. A VARCHAR column isn't a good primary key; a better key type would be an INT (or a BIGINT if you expect more than 2^31-1 players ;)). Key lookup with integers is faster compared to key lookup with strings. Also consider that you will have to reference players by their primary key in other tables (detail tables).

    The easiest way is to have SQL Server create such an integer key for you. You can do this by adding an IDENTITY column to the table, and make that column the primary key. In that case, for each insert into the player table a key will be assigned to the player. You will have to add an INDEX on the table for the player_name column though as at some point you will have to look up players by their name.

    Eg:

    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. As Gordon already pointed out, structs or arrays of structs can't be stored in a table as such. A good way of designing your tables is for each logically grouped set of data for a player, create a (detail) table that links to the player table. Relational databases have an easier time with tables that have as few columns as possible.

    For a group of information (a struct) that does not change like a player_location you could argue to store this information directly in the player table (columns X, Y and Z). Better still is to have that logically grouped set of information in a separate table player_location. You would then have a 1:1 relation between the player table and the location table.

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

    Other groups of information like player_equipment will continually grow, as I assume players will pick up equipment as they play through the game. Another aspect is that you will probably add new equipment as the game grows (through mods say). Say you have 100 types of equipment now but in your expansion you would add 100 new types of equipment. Say you take the previous advice, create a table with 100 columns and then when you release the mod you would then have to add 100 new columns.

    Having so many columns in a table is a bad idea in itself, plus you would have to alter the equipment table when you release the mod. Another aspect in that way of thinking is that you would have to store 100 (or 200 after the mod) columns of data that would not necessarily contain any relevant information. A player might only have 20 equipment and you would have to store 100 (200) columns. That would be a waste of disk/memory space.

    A better way to model this is to have a definition table that defines the equipment and a player-equipment table that stores what equipment the player is holding. Example:

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

    When you release a new mod, you would add new equipment in the equipment table and when a player picks up new equiment you would add a row to the player_equipment table referencing the equipment by its ID.

Anyway those are some thoughts for you to delve in deeper. A good database model will allow you the write queries in an easier way (less complex) and will allow the database to consume less memory and disk space.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!