简体   繁体   English

SQL Server 2008:我可以为此使用约束吗?

[英]SQL Server 2008: Can I use a constraint for this?

I have a table with three fields, User , City and Country , where exactly one of the fields must be non- NULL at all times. 我有一个包含三个字段的表: UserCityCountry ,其中恰好其中一个字段必须始终为非NULL Can I use an SQL constraint for this or should I rethink what I'm doing? 我可以为此使用SQL约束还是应该重新考虑我在做什么?

The scenario is that my database should contain documents that can be attached to users, cities or countries. 场景是我的数据库应包含可以附加到用户,城市或国家的文档。 So a row in this table contains exactly one document for either a user, a city or a country. 因此,此表中的一行仅包含一个针对用户,城市或国家的文档。 However, one should be able to search for all documents as well, regardless of what entity it has been "attached" to. 但是,无论文档被“附加”到哪个实体,都应该能够搜索所有文档。

The reason I'm not using three different tables instead is that I want to avoid having to JOIN the three tables when searching for documents in all of the three places. 我之所以没有使用三个不同的表的原因是,我想避免在所有三个地方搜索文档时必须JOIN三个表。 I'm imagining that the kind of denormalization I'm attempting to use here will improve performance, but I'm not sure. 我在想我要在这里使用的那种非规范化可以提高性能,但是我不确定。

Thoughts? 有什么想法吗?

If I understand properly, the following SQL should add the constraint you are looking for: 如果我理解正确,则以下SQL应该添加您要查找的约束:

ALTER TABLE YourTableName
ADD CONSTRAINT CK_TestNullCount 
    CHECK (Case When [user] is NULL Then 0 Else 1 End 
           + Case When City Is NULL Then 0 Else 1 End 
           + Case When Country Is NULL Then 0 Else 1 End = 1)

Put them in a single table Locations with columns LocationID, LocationName, and (if needed) LocationType (User, City, Country). 将它们放在具有位置ID,位置名称和(如果需要)位置类型(用户,城市,国家/地区)列的单个表位置中。 You need only a single join to discover the "location" of the document and you don't have to worry about which field to select to get the name of the location. 您只需一个联接即可发现文档的“位置”,而不必担心选择哪个字段来获取位置名称。

With this technique, you can enforce the "one and only one" location requirement with a simple non-null foreign key constraint. 使用此技术,您可以使用简单的非空外键约束来强制执行“一个且只有一个”位置要求。

Not sure if you can do it with a CHECK CONSTRAINT - I'm been playing around but nothing seems to really work in the end :-( 不知道您是否可以使用“检查约束”来完成它-我一直在玩,但是最后似乎没有任何效果:-(

But you could always create an INSTEAD OF INSERT (and possibly an INSTEAD OF UPDATE ) trigger on the table to check these conditions, and if they're not met, throw an exception using RAISERROR and the row won't be inserted (or updated). 但是您总是可以在表上创建一个INSTEAD OF INSERT (可能还有一个INSTEAD OF UPDATE )触发器来检查这些条件,如果不满足,则使用RAISERROR引发异常,并且不会插入(或更新该行) )。

I'd suggest sticking with the FK scenario. 我建议坚持FK方案。 Here's how I'd ensure that a document is tied to one, and only one DocumentType (what you're calling attached-to). 这是我要确保一个文档绑定到一个文档,并且只有一个DocumentType (您称之为附件)的方式。

Here's a very simplified relationship. 这是一个非常简化的关系。 I realize you've already got the 3 columns on your Document table, but consider making that a FK. 我知道您的文档表上已经有3列,但是请考虑将其设为FK。 替代文字

Then load up your Document types with the valid range of values. 然后使用有效范围的值加载您的文档类型。

替代文字

When inserting data, you'll be writing the type as varchar, rather than an int. 插入数据时,您将把类型写为varchar,而不是int。 This shouldn't cause perf issues, and will help you in reporting, etc with the denormalized schema. 这不会引起性能问题,并且可以帮助您使用非规范化模式进行报告等。

替代文字

Why don't you have two columns, one called LocationId and one called LocationTypeId. 为什么没有两列,一列称为LocationId,另一列称为LocationTypeId。 You can then left join onto all three tables: 然后,您可以将联接保留在所有三个表上:

SELECT COALESCE(User.Name, City.Name, Country.Name) 
FROM Location
INNER JOIN LocationType ON Location.LocationTypeId = LocationType.LocationTypeId
LEFT JOIN User ON Location.LocationId = User.Id AND Location.LocationTypeId = 1
LEFT JOIN City ON Location.LocationId = City.Id AND Location.LocationTypeId = 2
LEFT JOIN Country ON Location.LocationId = Country.Id AND Location.LocationTypeId = 3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在SQL Server 2008 R2中复制行 - How can i copy a row in sql server 2008 r2 如何在SQL Server 2008中找到缺少的日期范围? - How can I find missing date range in sql server 2008? 无法在SQL Server 2008中创建序列 - Can't create sequence in SQL Server 2008 无法在SQL Server Express 2008中使用SQL Server身份验证 - Unable to use SQL Server Authentication with SQL Server Express 2008 从SQL Server 2008升级应用程序以使用SQL Server 2016 - Upgrade Application to use SQL Server 2016 from SQL Server 2008 在SQL Server 2008中,如果我不希望其为null,则应使用哪个默认日期? - In SQL Server 2008, what default date should I use if I don't want it to be null? 我可以在具有相同实例的 SQL Server 上使用链接服务器到 SQL Server 吗? - Can I use linkserver to SQL Server on SQL Server with the same instance? 如何使用 C# 从 SQL Server 2008 的作业生成脚本? - How can use C# to generate a script from jobs of SQL Server 2008? 是否可以使用C#代码将文件.sql(我使用MSSQL SERVER 2008 R2)转换为.bacpac? - Is it possible convert file .sql (I use MSSQL SERVER 2008 R2) to .bacpac with C# code? 如何在MySQL服务器和Microsoft SQL Server 2008上同时使用NHibernate - How to use NHibernate with both MySQL server and Microsoft SQL server 2008
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM