我应该使用 SQL_Variant 数据类型吗?

发布于 2024-12-29 09:58:49 字数 919 浏览 3 评论 0原文

使用 SQL Server 2005 SP4,我正在设计一个数据库表。

这是表 DDL

CREATE TABLE CPSync4D.ProjectProfilerOption
(
    ProjectProfilerOptionID     INT  IDENTITY(1,1) CONSTRAINT PK_ProjectProfilerOption_ProjectProfilerOptionID PRIMARY KEY 
   ,ProjectID                   INT  CONSTRAINT FK_ProjectProfilerOption_Project_ProjectID FOREIGN KEY(ProjectID) REFERENCES CPSync4D.Project(ProjectID) ON DELETE CASCADE
   ,ProfilerOptionID            TINYINT CONSTRAINT FK_ProjectProfilerOption_ProfilerOption_ProfilerOptionID  FOREIGN KEY(ProfilerOptionID) REFERENCES CPSync4D.ProfilerOption (ProfilerOptionID) 
   ,ProfilerOptionValue         sql_variant  NOT NULL   

)
Go

ProfilerValueType”,或 12.52 或 20 等(不超过两位小数且整数值小于 100)

profileroptionvalue 列可以保存最多 30 个字符的字符串、整数或小数值,例如值是“ 使用 sql_variant 或 varchar(30)...?我以前从未使用过 sql_variant,并且不确定不使用对数据库设计有何影响。

使用 sql_variant 的任何陷阱...与 .net 代码

using SQL Server 2005 with SP4 and I am designing a database table.

Here is the table DDL

CREATE TABLE CPSync4D.ProjectProfilerOption
(
    ProjectProfilerOptionID     INT  IDENTITY(1,1) CONSTRAINT PK_ProjectProfilerOption_ProjectProfilerOptionID PRIMARY KEY 
   ,ProjectID                   INT  CONSTRAINT FK_ProjectProfilerOption_Project_ProjectID FOREIGN KEY(ProjectID) REFERENCES CPSync4D.Project(ProjectID) ON DELETE CASCADE
   ,ProfilerOptionID            TINYINT CONSTRAINT FK_ProjectProfilerOption_ProfilerOption_ProfilerOptionID  FOREIGN KEY(ProfilerOptionID) REFERENCES CPSync4D.ProfilerOption (ProfilerOptionID) 
   ,ProfilerOptionValue         sql_variant  NOT NULL   

)
Go

profileroptionvalue column can hold either a string upto 30 characters, integer or decimal values e.g. values are "ProfilerValueType", or 12.52 or 20 etc. (no more than than two decimals and integer values are less than 100)

Should I use sql_variant or varchar(30)...? I never used sql_variant before and not sure any implication of not using in terms of database design.

Any pitfalls of using sql_variant...with .net code

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

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

发布评论

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

评论(3

自控 2025-01-05 09:58:49

显式转换的 10 个理由SQL Server 数据类型

作为一般规则,您应该避免使用 SQL Server 的 sql_variant
数据类型。除了占用内存之外,sql_variant 还受到限制:

  • 变体不能是主键或外键的一部分。 (从 SQL Server 2005 开始,这一点不再成立。请参阅下面的更新)
  • 变体不能成为计算列的一部分。
  • 变体不能与 WHERE 子句中的 LIKE 一起使用。
  • OLE DB 和 ODBC 提供程序自动将变体转换为 nvarchar(4000) — 哎呀!

为避免出现问题,请始终将 sql_variant 数据类型显式转换为
你使用它们。使用任何你喜欢的方法,只是不要尝试使用
未转换的 sql_variant 数据类型。

我以前没有使用过 sql_variant ,但考虑到这些限制和性能影响,我会首先考虑替代方案。

以下是我最喜欢到最不喜欢的解决方案

  • 只需创建三个不同的列。 3 不同的数据类型(应该)意味着在客户端和服务器端有 3 种不同的解释方式。
  • 如果这不是一个选项,请使用 VARCHAR 列,这样您至少可以使用 LIKE 语句。
  • 使用sql_variant 数据类型。

编辑 Cudo 为 ta.speot.is

变体可以成为外键主键的一部分

唯一、主或外键可能包含以下类型的列
sql_variant,而是组成数据值的总长度
特定行的键不应超过行的最大长度
指数。这是 900 字节

10 reasons to explicitly convert SQL Server data types

As a general rule, you should avoid using SQL Server’s sql_variant
data type. Besides being a memory hog, sql_variant is limited:

  • Variants can’t be part of a primary or foreign key. (this doesn't hold as of SQL Server 2005. See update below)
  • Variants can’t be part of a computed column.
  • Variants won’t work with LIKE in a WHERE clause.
  • OLE DB and ODBC providers automatically convert variants to nvarchar(4000) — ouch!

To avoid problems, always explicitly convert sql_variant data types as
you use them. Use any method you please, just don’t try to work with
an unconverted sql_variant data type.

I haven't used sql_variant before but with these restrictions and performance implications in mind, I would first look at alternatives.

Following would be my most to least prefered solution

  • Simply create three different columns. 3 Different data types (should) mean 3 different ways of interpreting it both at the client side and server side.
  • If that is not an option, use a VARCHAR column so you can at least use LIKE statements.
  • Use the sql_variant data type.

Edit Cudo's to ta.speot.is

Variants can be part of a primary of foreign key

A unique, primary, or foreign key may include columns of type
sql_variant, but the total length of the data values that make up the
key of a specific row should not be more than the maximum length of an
index. This is 900 bytes

長街聽風 2025-01-05 09:58:49

我知道我的回答有点晚了,但这里制作的表格看起来有点像应用程序配置表。作为给出的建议的替代方案,让我们考虑不要将自己限制在 30 甚至 8000 个字符。我们还可以让它更加独立和用户可定义。

考虑到这些想法,为什么不将“配置文件”信息保存为 XML 数据类型,甚至允许多个级别的设置呢?您可能不再需要 ProfilerOptionID 等列,并且可能能够将其简化为一个简单的控制表。

I know my answer is a bit late but the table being made here looks a bit like an application configuration table. As an alternative to the suggestions given, let's think about not limiting ourselves to 30 or even 8000 characters. Let's also make it a bit more self contained and user definable.

With those thoughts in mind, why not save the "profile" information as an XML data type which would even allow multiple levels of settings? You probably wouldn't need such columns as ProfilerOptionID anymore and might be able to get this down to one simple control table.

も星光 2025-01-05 09:58:49

值得注意的是,不可能隐式复制 sql_variant 列。

例如,创建一个名为 CPSync4D.ProjectProfilerOption_bkp 的 CPSync4D.ProjectProfilerOption 备份模式

,然后

Insert into CPSync4D.ProjectProfilerOption_bkp
(
    ProjectProfilerOptionID
   ,ProjectID
   ,ProfilerOptionID
   ,ProfilerOptionValue 
)
SELECT 
    ProjectProfilerOptionID
   ,ProjectID
   ,ProfilerOptionID
   ,ProfilerOptionValue 
FROM CPSync4D.ProjectProfilerOption 

备份表中 ProfilerOptionValue 的所有值都将为 varchar

另请注意:我被告知 SQL_Variant 不能在复制中使用,但事实并非如此是的。当然,可以使用 SQL 2008 R2(我正在使用)来完成,因为我刚刚完成了它,但这可能对于旧版本来说是正确的(我没有任何旧版本可以检查,所以无法证实或否认这一点)。

但事实是,如果您确实复制了一个包含 SQL 变体的表并且有大量数据,然后出现问题并且您需要手动修复数据,那么您可能需要编写一段令人讨厌的 SQL 。这是因为复制数据时,无法在同一个复制语句中复制多个基本类型。我猜想复制不会出现此问题,因为它不会复制多行(快照明显例外,但使用 bcp)。

附注我意识到这是一篇旧帖子,但将其放在这里供其他有相同问题的未来访客使用。

Its worth noting that it is not possible to copy the sql_variant column implicitly.

e.g. Create a backup schema of CPSync4D.ProjectProfilerOption called CPSync4D.ProjectProfilerOption_bkp

and then

Insert into CPSync4D.ProjectProfilerOption_bkp
(
    ProjectProfilerOptionID
   ,ProjectID
   ,ProfilerOptionID
   ,ProfilerOptionValue 
)
SELECT 
    ProjectProfilerOptionID
   ,ProjectID
   ,ProfilerOptionID
   ,ProfilerOptionValue 
FROM CPSync4D.ProjectProfilerOption 

All of the values for ProfilerOptionValue in the backup table will be varchar

Note also: I have been told that the SQL_Variant cannot be used in replication but this is not true. Certainly it can be done with SQL 2008 R2 (that I am using) because I have just done it but this may have been true for older versions (I don't have any older versions to check with so cannot confirm or deny this).

What is true though, is that if you do replicate a table with a SQL Variant in it and have a lot of data and then something goes wrong and you need to fix the data manually, then you might have a nasty piece of SQL to write. This is because when copying the data you cannot copy with several base types in the same copy statement. I guess that replication doesn't have this issue because it does not copy multiple rows (with the obvious exception of the snapshot but that uses bcp).

ps. I realise this is an old post but put this here for other future visitors with the same question.

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