复合主键/外键令人头痛

发布于 2024-11-05 06:47:44 字数 1322 浏览 0 评论 0原文

我正在使用 SQL Server 2008 R2、C# 和 ASP.Net。我有一个表,其中包含一个复合主键,其中包含票证编号以及该票证在表中出现的次数。票证频率由 C# 代码计算:

VTTTickets.InsertParameters[0].DefaultValue = VTTTTicketNoBox.Text;
string CommString = "SELECT COUNT(*) FROM [Tickets] WHERE [Ticket_No] = " + 
VTTTTicketNoBox.Text;
string ConnString = ConfigurationManager.ConnectionStrings[1].ConnectionString;
OdbcConnection Conn = new OdbcConnection(ConnString);
Conn.Open();
OdbcCommand FooCommand = newOdbcCommand(CommString,Conn);
int FooVal = Convert.ToInt32(FooCommand.ExecuteScalar()) + 1;
VTTTickets.InsertParameters[1].DefaultValue = Convert.ToString(FooVal);
VTTTTicketNoBox.Text = "";
Conn.Close();

我的表约束/等代码

CONSTRAINT [PK_Tickets] PRIMARY KEY CLUSTERED 
([Ticket_No] ASC, [Ticket_Sub_No] ASC)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = ON,
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
CONSTRAINT [Unique_Ticket_No] UNIQUE NONCLUSTERED 
([Ticket_No] ASC)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = ON,     
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
) ON [PRIMARY]
GO

唯一约束的原因是因为主组合键的该部分也是其他两个表的外键。 我不断收到的错误是当它对我大喊大叫时,因为唯一约束列中存在重复值。一旦一切从开发转移到生产,就可能会发生这种情况,因为可能会重新提交票证。

有没有什么方法可以使外键不受唯一键约束? 如果没有,我该如何解决这个问题?

I am working with SQL Server 2008 R2, C# and ASP.Net. I have a table that has a composite Primary key consisting of a ticket number, and the number of times that ticket appears in the table. The ticket frequency is calculated by the C# Code:

VTTTickets.InsertParameters[0].DefaultValue = VTTTTicketNoBox.Text;
string CommString = "SELECT COUNT(*) FROM [Tickets] WHERE [Ticket_No] = " + 
VTTTTicketNoBox.Text;
string ConnString = ConfigurationManager.ConnectionStrings[1].ConnectionString;
OdbcConnection Conn = new OdbcConnection(ConnString);
Conn.Open();
OdbcCommand FooCommand = newOdbcCommand(CommString,Conn);
int FooVal = Convert.ToInt32(FooCommand.ExecuteScalar()) + 1;
VTTTickets.InsertParameters[1].DefaultValue = Convert.ToString(FooVal);
VTTTTicketNoBox.Text = "";
Conn.Close();

My tables constraint/etc code

CONSTRAINT [PK_Tickets] PRIMARY KEY CLUSTERED 
([Ticket_No] ASC, [Ticket_Sub_No] ASC)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = ON,
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
CONSTRAINT [Unique_Ticket_No] UNIQUE NONCLUSTERED 
([Ticket_No] ASC)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = ON,     
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
) ON [PRIMARY]
GO

The reason for the unique constraint is because that part of the primary composite key is also a foreign key for two other tables.
The error I keep getting is when it yells at me for there being a duplicate values present in the unique constrained column. This may occur once everything moves to production from development, as a ticket may be re-submitted.

Is there any way to make the foreign key without the unique key constraint?
If not, how do I get around this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最近可好 2024-11-12 06:47:44

这是我们在编程中经常遇到的情况之一。技术_A 不会让我执行操作_B,但它应该!然后,在用头撞墙一段时间后,我们放弃了(或者前往 Stackoverflow)。我们这样做是因为我们没有按照预期使用该技术(这没关系,这就是我们学习的方式!)

这里的问题是您的数据库架构。

您试图用一张桌子做太多事情。您不应将票证(同一张票证可能存在多次)存储在您正在跟踪发生次数的同一个表中。

在我看来,有两个很好的策略可以纠正这种情况。首先,我将创建一个带有单列主键的门票表。然后,我将创建一个表来存储票证的每个实例。

在此处输入图像描述

示例:Ticket43 已关闭,但重新打开并再次关闭。这意味着(如果我没看错你的问题)该票证有两个实例。这意味着它在原始表中将有两个条目,但在我建议的新架构中,它在 Tickets 中将有一个条目,在 Ticket_Instances 中将有两个条目。

注意:您需要确保在 Tickets 中存储在实例之间永不更改的票证信息,并将特定于实例的票证信息存储在 Ticket_Instances 中。

要记录票数,我要做的第一件事就是简单地编写一个视图或 SQL 代码,如下所示:

SELECT
  count(*) as TicketCount,
  TicketID
FROM
  Ticket_Instances as TI
GROUP BY
  TicketID

如果您不想按需计算 ,那么我建议使用:

  • ASP.NET 缓存(运行上面的 SQL,将其塞入缓存,TTL 为 10 分钟)
  • 使用由触发器填充的 Ticket_Counts 表

我怀疑您会更喜欢选项 2(尽管我会使用选项1)。

触发方法:

假设Ticket_Instances可能永远不会被删除,您只需要一个插入触发器。您将在插入时在 Ticket_Instances 表上创建一个触发器,该触发器 SQL 将执行以下操作:

  • 如果 Ticket_Counts 中不存在 TicketID,则将 TicketID 插入 Ticket_Counts 中,其中 TicketCount 为 0
  • 然后,将 TicketCount 增加 TicketID 的 1在 Ticket_Counts 中

使用此方法,您只需通过 TicketID 访问 Ticket_Counts 即可获取该特定 Ticket 的出现次数。

我想您会发现一旦更新架构,约束错误就会消失。

This is one of those situations that we run into a lot in programming. Technology_A will not let me do Operation_B, but it should! Then, after beating our heads against the wall for a while, we give up (or head to Stackoverflow). We do this because we're not using the technology as it was intended (which is OK, that's how we learn!)

The issue here is your database schema.

You are trying to do too much with one table. You should not store tickets (where the same ticket may exist more than once) in the same table that you are tracking # of occurrences.

In my opinion, there are two good strategies to correct this situation. First, I would create a tickets table, with a single-column Primary Key. Then, I would create a table that stores each instance of a ticket.

enter image description here

Example: Ticket43 is closed, but re-opened and closed again. This means (if I read your question right), that the ticket had two instances. This means it would have two entries in your original table, but in my new proposed schema, it would have one entry in Tickets, and two entries in Ticket_Instances.

Note: You will want to make sure to store ticket information that never changes between instances in Tickets, and instance-specific Ticket information in Ticket_Instances.

To record Ticket Counts, the first thing I would do is simply write a view or bit of SQL like the following:

SELECT
  count(*) as TicketCount,
  TicketID
FROM
  Ticket_Instances as TI
GROUP BY
  TicketID

If you do not want to have to calculate this on demand, then I suggest making use of:

  • ASP.NET Cache (Run the above SQL, jam it into cache with a TTL of 10 minutes)
  • Use the Ticket_Counts table that is populated by a trigger

I suspect you will prefer option 2 there (although I would use option 1).

Trigger Method:

Assuming Ticket_Instances may never be deleted, you only need an Insert Trigger. You would create a trigger on the Ticket_Instances table upon Insert, and that trigger SQL would do the following:

  • If the TicketID does not exist in Ticket_Counts, then Insert the TicketID into Ticket_Counts with TicketCount of 0
  • Then, Increase the TicketCount by 1 of the TicketID in Ticket_Counts

With this method, you only need to access Ticket_Counts by TicketID to get the # of occurrences of that particular Ticket.

I think you will find that your constraint errors disappear once you update your schema.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文