数据库问题 - 外键始终为 Null (T-SQL)
Problem with Database - Foreign Key always Null (T-SQL)
我的问题可能描述起来有点长,因为我们正在进行的项目有点大,但我会尽量准确。
基本上我们正在开发一个基于网络的伤口管理(大学项目的一部分),用户可以在其中输入伤口并设置其他信息,例如大小、稠度、上传图片、选择位置……。
所有这些信息都应存储在数据库中(我们正在使用 MS SQL Studio 和 Visual Studio 2017),用户以后也可以在其中检索它以在模块上查看它。
我们现在面临的问题是,如果我们想向用户展示一个特殊伤口的伤口,我们无法让外键起作用。
我们可以通过 casenumber 进行过滤(这是有效的)但是我们不能通过伤口的 ID 来过滤伤口信息(每个伤口都有一个唯一的 ID)——所以如果我们选择一个伤口,我们仍然会得到关于所有伤口的信息为给定的 casenr 存储。
这是我们的 "main-table",其中每个伤口都有一个唯一的 ID,它也是一个升序标识列:
[wound_id] INT IDENTITY (1, 1) NOT NULL,
[wound_type] VARCHAR (500) NULL,
[wound_description] VARCHAR (500) NULL,
[decuGrade] INT NULL,
[wound_comments] VARCHAR (500) NULL,
[wound_timeReal] DATETIME NULL,
[wound_timeGiven] DATETIME NULL,
[casenumber] INT NULL,
[username] VARCHAR (50) NULL,
PRIMARY KEY CLUSTERED ([wound_id] ASC)
);
如果用户输入信息并点击"Next",后面的代码中会调用一个函数来填充table:
_db.SaveWoundDetails(casenr, woundValue, decu, additional_info, realTime, givenBackDocDate, user);
这导致我们的数据库-class,我们在那里查询数据库,在这种情况下:
public void SaveWoundDetails(int casenr, string woundType, int decuGrade, string woundComment, DateTime timeReal, DateTime timeGiven , string user)
{
var table = ConfigurationManager.AppSettings["woundDetailsTable"];
var insertQuery = "INSERT INTO " + table + "(casenumber, wound_type, decuGrade, wound_comments, wound_timeReal, wound_timeGiven, username) VALUES (@casenr, @woundType, @decuGrade, @woundComment, @timeReal, @timeGiven, @user)";
var cmd = new SqlCommand(insertQuery);
cmd.Parameters.AddWithValue("@casenr", casenr);
cmd.Parameters.AddWithValue("@woundType", woundType);
cmd.Parameters.AddWithValue("@decuGrade", decuGrade);
cmd.Parameters.AddWithValue("@woundComment", woundComment);
cmd.Parameters.AddWithValue("@timeReal", timeReal);
cmd.Parameters.AddWithValue("@timeGiven", timeGiven);
cmd.Parameters.AddWithValue("@user", user);
var db = DatabaseController.getDataBaseController();
try
{
var sqlcmd = db.executeSQL(cmd);
}
catch (SqlException e)
{
}
}
连接等在数据库处理程序中 class 目前不相关。
到这里为止一切正常。但是现在我们有第二个 table 来获取更多关于伤口的信息,下次点击时也会填写,与此相关 table:
CREATE TABLE [dbo].[epadoc_mod_wound_progress] (
[progress_id] INT IDENTITY (1, 1) NOT NULL,
[wound_length] INT NULL,
[wound_width] INT NULL,
[wound_depth] INT NULL,
[wound_surrounding] VARCHAR (500) NULL,
[wound_consistence] VARCHAR (500) NULL,
[wound_state] VARCHAR (200) NULL,
[wound_painscale] VARCHAR (MAX) NULL,
[wound_itch] VARCHAR (MAX) NULL,
PRIMARY KEY CLUSTERED ([progress_id] ASC)
使用插入方法:
public void SaveWoundProgress(int woundLength, int woundWidth, int woundDepth, string woundSurrounding, string woundConsistence, string woundState, string woundPainScale, string woundItch)
{
var table = ConfigurationManager.AppSettings["woundProgressTable"];
var insertQuery = "INSERT INTO " + table + "(wound_length,wound_width,wound_depth, wound_surrounding, wound_consistence, wound_state, wound_painscale, wound_itch) VALUES (@woundLength, @woundWidth, @woundDepth, @woundSurrounding, @woundConsistence, @woundState, @woundPainScale, @woundItch)";
var cmd = new SqlCommand(insertQuery);
cmd.Parameters.AddWithValue("@woundLength", woundLength);
cmd.Parameters.AddWithValue("@woundWidth", woundWidth);
cmd.Parameters.AddWithValue("@woundDepth", woundDepth);
cmd.Parameters.AddWithValue("@woundSurrounding", woundSurrounding);
cmd.Parameters.AddWithValue("@woundConsistence", woundConsistence);
cmd.Parameters.AddWithValue("@woundState", woundState);
cmd.Parameters.AddWithValue("@woundPainScale", woundPainScale);
cmd.Parameters.AddWithValue("@woundItch", woundItch);
var db = DatabaseController.getDataBaseController();
try
{
var sqlcmd = db.executeSQL(cmd);
}
catch (SqlException e)
{
}
}
和方法
_db.SaveWoundProgress(wound_length, wound_width, wound_depth, woundArea, woundEdge, woundStatus, painStatus, itchStatus);
在上述方法之后执行
我知道如何在两个 table 之间创建外键,但我们尝试的一切都失败了 - 如果我们尝试使用非 NULL 的外键集执行它,我们将得到一个空值 -异常。
我们尝试的示例:
CONSTRAINT [FK_epadoc_mod_wound_details] FOREIGN KEY ([wound_id])
REFERENCES [dbo].[epadoc_mod_wound_progress] ([progress_id])
如果我们这样设置外键,那是行不通的。
我们得出的结论是,这两个方法执行时一定是调用堆栈有问题 - 但我们不知道如何解决它。
也许我们必须将 INSERT 查询中的外键设置为显式变量?
我们要实现的是把details-table的wound_id作为progress-table的外键,这样以后就可以改伤口了(例如,如果它治愈了,用户可以重新输入新的尺寸等)并且我们可以按 ID 过滤以仅向患者显示一个伤口,而不是在单击特定伤口时同时显示所有伤口。
遗憾的是我不是大数据库专家所以我希望你能听懂我的解释:)。
感谢您的帮助!
您的 epadoc_mod_wound_progress
需要包含一个 [wound_id] INT NOT NULL
列。这是你的外键应该建立的基础,这样一个伤口可以有多个伤口进展。然后,在您的插入语句中,您将插入在 woundDetail
table 中生成的 wound_id
insert into epadoc_mod_wound_progress
.
试图添加评论,但我没有 50 声望。
据我所知,我假设您正在尝试在 "main table" 和 "epadoc_mod_wound_progress" table 之间实现一对多关系,对吗?
如果是这样,您似乎在 "epadoc_mod_wound_progress" table 中没有存储 wound_id 的字段,如果您是不存储 wound_id ?
建议epadoc_mod_wound_progress table的主键是wound_id和progress_id的连接键,wound_id也是外键链接到主要 table.
在 table epadoc_mod_wound_progress
中必须有一个 wound_id INT NOT NULL
列作为外键。
还必须将约束添加到外键 table,即 1 的 n 侧的 table到 n 关系。假设maintable的名字是epadoc_mod_wound_details
(你没显示):
ALTER TABLE dbo.epadoc_mod_wound_progress
ADD CONSTRAINT FK_progress_details FOREIGN KEY (wound_id)
REFERENCES dbo.epadoc_mod_wound_details (wound_id)
ON DELETE CASCADE
此外,添加ON DELETE CASCADE
伤口细节的进度将在您删除伤口细节时自动删除。
我的问题可能描述起来有点长,因为我们正在进行的项目有点大,但我会尽量准确。
基本上我们正在开发一个基于网络的伤口管理(大学项目的一部分),用户可以在其中输入伤口并设置其他信息,例如大小、稠度、上传图片、选择位置……。 所有这些信息都应存储在数据库中(我们正在使用 MS SQL Studio 和 Visual Studio 2017),用户以后也可以在其中检索它以在模块上查看它。
我们现在面临的问题是,如果我们想向用户展示一个特殊伤口的伤口,我们无法让外键起作用。 我们可以通过 casenumber 进行过滤(这是有效的)但是我们不能通过伤口的 ID 来过滤伤口信息(每个伤口都有一个唯一的 ID)——所以如果我们选择一个伤口,我们仍然会得到关于所有伤口的信息为给定的 casenr 存储。
这是我们的 "main-table",其中每个伤口都有一个唯一的 ID,它也是一个升序标识列:
[wound_id] INT IDENTITY (1, 1) NOT NULL,
[wound_type] VARCHAR (500) NULL,
[wound_description] VARCHAR (500) NULL,
[decuGrade] INT NULL,
[wound_comments] VARCHAR (500) NULL,
[wound_timeReal] DATETIME NULL,
[wound_timeGiven] DATETIME NULL,
[casenumber] INT NULL,
[username] VARCHAR (50) NULL,
PRIMARY KEY CLUSTERED ([wound_id] ASC)
);
如果用户输入信息并点击"Next",后面的代码中会调用一个函数来填充table:
_db.SaveWoundDetails(casenr, woundValue, decu, additional_info, realTime, givenBackDocDate, user);
这导致我们的数据库-class,我们在那里查询数据库,在这种情况下:
public void SaveWoundDetails(int casenr, string woundType, int decuGrade, string woundComment, DateTime timeReal, DateTime timeGiven , string user)
{
var table = ConfigurationManager.AppSettings["woundDetailsTable"];
var insertQuery = "INSERT INTO " + table + "(casenumber, wound_type, decuGrade, wound_comments, wound_timeReal, wound_timeGiven, username) VALUES (@casenr, @woundType, @decuGrade, @woundComment, @timeReal, @timeGiven, @user)";
var cmd = new SqlCommand(insertQuery);
cmd.Parameters.AddWithValue("@casenr", casenr);
cmd.Parameters.AddWithValue("@woundType", woundType);
cmd.Parameters.AddWithValue("@decuGrade", decuGrade);
cmd.Parameters.AddWithValue("@woundComment", woundComment);
cmd.Parameters.AddWithValue("@timeReal", timeReal);
cmd.Parameters.AddWithValue("@timeGiven", timeGiven);
cmd.Parameters.AddWithValue("@user", user);
var db = DatabaseController.getDataBaseController();
try
{
var sqlcmd = db.executeSQL(cmd);
}
catch (SqlException e)
{
}
}
连接等在数据库处理程序中 class 目前不相关。
到这里为止一切正常。但是现在我们有第二个 table 来获取更多关于伤口的信息,下次点击时也会填写,与此相关 table:
CREATE TABLE [dbo].[epadoc_mod_wound_progress] (
[progress_id] INT IDENTITY (1, 1) NOT NULL,
[wound_length] INT NULL,
[wound_width] INT NULL,
[wound_depth] INT NULL,
[wound_surrounding] VARCHAR (500) NULL,
[wound_consistence] VARCHAR (500) NULL,
[wound_state] VARCHAR (200) NULL,
[wound_painscale] VARCHAR (MAX) NULL,
[wound_itch] VARCHAR (MAX) NULL,
PRIMARY KEY CLUSTERED ([progress_id] ASC)
使用插入方法:
public void SaveWoundProgress(int woundLength, int woundWidth, int woundDepth, string woundSurrounding, string woundConsistence, string woundState, string woundPainScale, string woundItch)
{
var table = ConfigurationManager.AppSettings["woundProgressTable"];
var insertQuery = "INSERT INTO " + table + "(wound_length,wound_width,wound_depth, wound_surrounding, wound_consistence, wound_state, wound_painscale, wound_itch) VALUES (@woundLength, @woundWidth, @woundDepth, @woundSurrounding, @woundConsistence, @woundState, @woundPainScale, @woundItch)";
var cmd = new SqlCommand(insertQuery);
cmd.Parameters.AddWithValue("@woundLength", woundLength);
cmd.Parameters.AddWithValue("@woundWidth", woundWidth);
cmd.Parameters.AddWithValue("@woundDepth", woundDepth);
cmd.Parameters.AddWithValue("@woundSurrounding", woundSurrounding);
cmd.Parameters.AddWithValue("@woundConsistence", woundConsistence);
cmd.Parameters.AddWithValue("@woundState", woundState);
cmd.Parameters.AddWithValue("@woundPainScale", woundPainScale);
cmd.Parameters.AddWithValue("@woundItch", woundItch);
var db = DatabaseController.getDataBaseController();
try
{
var sqlcmd = db.executeSQL(cmd);
}
catch (SqlException e)
{
}
}
和方法
_db.SaveWoundProgress(wound_length, wound_width, wound_depth, woundArea, woundEdge, woundStatus, painStatus, itchStatus);
在上述方法之后执行
我知道如何在两个 table 之间创建外键,但我们尝试的一切都失败了 - 如果我们尝试使用非 NULL 的外键集执行它,我们将得到一个空值 -异常。
我们尝试的示例:
CONSTRAINT [FK_epadoc_mod_wound_details] FOREIGN KEY ([wound_id])
REFERENCES [dbo].[epadoc_mod_wound_progress] ([progress_id])
如果我们这样设置外键,那是行不通的。
我们得出的结论是,这两个方法执行时一定是调用堆栈有问题 - 但我们不知道如何解决它。 也许我们必须将 INSERT 查询中的外键设置为显式变量?
我们要实现的是把details-table的wound_id作为progress-table的外键,这样以后就可以改伤口了(例如,如果它治愈了,用户可以重新输入新的尺寸等)并且我们可以按 ID 过滤以仅向患者显示一个伤口,而不是在单击特定伤口时同时显示所有伤口。
遗憾的是我不是大数据库专家所以我希望你能听懂我的解释:)。
感谢您的帮助!
您的 epadoc_mod_wound_progress
需要包含一个 [wound_id] INT NOT NULL
列。这是你的外键应该建立的基础,这样一个伤口可以有多个伤口进展。然后,在您的插入语句中,您将插入在 woundDetail
table 中生成的 wound_id
insert into epadoc_mod_wound_progress
.
试图添加评论,但我没有 50 声望。
据我所知,我假设您正在尝试在 "main table" 和 "epadoc_mod_wound_progress" table 之间实现一对多关系,对吗?
如果是这样,您似乎在 "epadoc_mod_wound_progress" table 中没有存储 wound_id 的字段,如果您是不存储 wound_id ?
建议epadoc_mod_wound_progress table的主键是wound_id和progress_id的连接键,wound_id也是外键链接到主要 table.
在 table epadoc_mod_wound_progress
中必须有一个 wound_id INT NOT NULL
列作为外键。
还必须将约束添加到外键 table,即 1 的 n 侧的 table到 n 关系。假设maintable的名字是epadoc_mod_wound_details
(你没显示):
ALTER TABLE dbo.epadoc_mod_wound_progress
ADD CONSTRAINT FK_progress_details FOREIGN KEY (wound_id)
REFERENCES dbo.epadoc_mod_wound_details (wound_id)
ON DELETE CASCADE
此外,添加ON DELETE CASCADE
伤口细节的进度将在您删除伤口细节时自动删除。