你能限制(数据库)表中的行数吗?

时间:2021-02-15 09:11:18

We have a database (SQL Server 2005) which we would like to get under source control. As part of that we are going to have a version table to store the current version number of the database. Is there a way to limit that table to only holding one row? Or is storing the version number in a table a bad idea?

我们有一个数据库(SQL Server 2005),我们希望在源代码管理下获得它。作为其中的一部分,我们将有一个版本表来存储数据库的当前版本号。有没有办法将该表限制为只保留一行?或者将版本号存储在表中是个坏主意?

Ended up using this approach:

结束使用这种方法:

CREATE TABLE [dbo].[DatabaseVersion]
    (
        [MajorVersionNumber] [int]  NOT NULL,
        [MinorVersionNumber] [int]  NOT NULL,
        [RevisionNumber] [int]  NOT NULL
    )
GO

Insert DataBaseVersion (MajorVersionNumber,  MinorVersionNumber,  RevisionNumber) values (0, 0, 0)
GO

CREATE TRIGGER DataBaseVersion_Prevent_Delete
ON DataBaseVersion INSTEAD OF DELETE
AS
BEGIN
    RAISERROR ('DatabaseVersion must always have one Row. (source = INSTEAD OF DELETE)', 16, 1) 
END
GO

CREATE TRIGGER DataBaseVersion_Prevent_Insert
ON DataBaseVersion INSTEAD OF INSERT
AS
BEGIN
    RAISERROR ('DatabaseVersion must always have one Row. (source = INSTEAD OF INSERT)', 16, 1) 
END
GO

7 个解决方案

#1


Use a trigger.

使用触发器。

#2


Generalize the table to hold "settings" and make it a key/value pair

对表进行概括以保持“设置”并使其成为键/值对

CREATE TABLE Settings (Key nvarchar(max), Value nvarchar(max))

Then make a unique index on Key.

然后在Key上创建一个唯一索引。

CREATE UNIQUE INDEX SettingsIDX ON Settings (Key)

That will create a table with unique key value pairs, one of which can be Version.

这将创建一个具有唯一键值对的表,其中一个可以是Version。

INSERT INTO Settings (Key, Value) VALUES ('Version','1');

#3


You can use Joe Celko's default+primary+check technique:

您可以使用Joe Celko的默认+主要+检查技术:

create table database_version (

  lock char(1) primary key default 'x' check (lock='x'),
  major_version_number int NOT NULL,
  minor_version_number int NOT NULL,
  revision_number int NOT NULL
);

Fiddle with it

摆弄它

#4


Not at all. You can simply add another, ascending column to that table (date, id, whatever), and then order the query by that other column descendingly and limit the result to 1 row:

一点也不。您可以简单地向该表添加另一个升序列(日期,标识,等等),然后按顺序将该查询按其他列排序并将结果限制为1行:

SELECT v.version FROM version v ORDER by v.date DESC LIMIT 1;

This way you even get a history of when each version was reached.

这样,您甚至可以获得每个版本到达时间的历史记录。

Edit:

The above sql query wouldn't work on SQL Server since it doesn't support the LIMIT statement. One would have to circumvent that deficiency, possibly as described in this "All Things SQL Server" blog entry.

上面的SQL查询在SQL Server上不起作用,因为它不支持LIMIT语句。人们不得不规避这种不足,可能就像这篇“All Things SQL Server”博客文章中所描述的那样。

#5


Based on your comments to other responses, it seems that:

根据您对其他回复的评论,似乎:

  1. You don't want users to just modify the value.
  2. 您不希望用户只修改该值。

  3. You only ever want one value returned.
  4. 您只需要返回一个值。

  5. The value is static, and scripted.
  6. 值是静态的,并且是脚本化的。

So, might I suggest that you script a function that returns the static value? Since you'll have to script an update to the version number anyway, you'll simply drop and recreate the function in your script when you update the database.

那么,我可以建议您编写一个返回静态值的函数吗?由于您无论如何都必须编写版本号的更新脚本,因此您只需在更新数据库时删除并重新创建脚本中的函数。

This has the advantage of being usable from a view or a procedure, and since a function's return value is read-only, it can't be modified (without modifying the function).

这具有可从视图或过程使用的优点,并且由于函数的返回值是只读的,因此不能修改它(不修改函数)。

EDIT: You also wouldn't have to worry about convoluted solutions for keeping a table constrained to one row.

编辑:您也不必担心将表限制为一行的复杂解决方案。

Just a suggestion.

只是一个建议。

#6


Keeping a version number for the database makes total sense. However I prefer to have a Version table that can contain multiple rows with fields for the version number, the time the update occured and the user that performed the upgrade.

保留数据库的版本号是完全有道理的。但是,我更喜欢有一个Version表,它可以包含多行,其中包含版本号字段,更新发生的时间以及执行升级的用户。

That way you know which upgrade scripts have been run and can easily see if they have been run out of sequence.

这样您就可以知道哪些升级脚本已经运行,并且可以轻松查看它们是否已经不按顺序运行。

When you want to read the current version number you can just read the most recent record.

如果要读取当前版本号,只需阅读最新记录即可。

If you only store one record you have know way of knowing if a script has been missed out. If you want to be really clever you can put checks in you upgrade scripts so they won't run unless the previous version of the database is correct.

如果您只存储一条记录,则您知道如何错过脚本。如果您想要非常聪明,可以在升级脚本中加入检查,这样除非先前版本的数据库正确,否则它们将无法运行。

#7


By creating the one allowable original row as part of the database initialization script, and (also in that script) removing Insert permissions to that table for all logins (Only Updates will be allowed)

通过创建一个允许的原始行作为数据库初始化脚本的一部分,并且(也在该脚本中)删除对该表的所有登录的插入权限(仅允许更新)

You might also want to disallow deletes as well...

你可能也想要禁止删除...

#1


Use a trigger.

使用触发器。

#2


Generalize the table to hold "settings" and make it a key/value pair

对表进行概括以保持“设置”并使其成为键/值对

CREATE TABLE Settings (Key nvarchar(max), Value nvarchar(max))

Then make a unique index on Key.

然后在Key上创建一个唯一索引。

CREATE UNIQUE INDEX SettingsIDX ON Settings (Key)

That will create a table with unique key value pairs, one of which can be Version.

这将创建一个具有唯一键值对的表,其中一个可以是Version。

INSERT INTO Settings (Key, Value) VALUES ('Version','1');

#3


You can use Joe Celko's default+primary+check technique:

您可以使用Joe Celko的默认+主要+检查技术:

create table database_version (

  lock char(1) primary key default 'x' check (lock='x'),
  major_version_number int NOT NULL,
  minor_version_number int NOT NULL,
  revision_number int NOT NULL
);

Fiddle with it

摆弄它

#4


Not at all. You can simply add another, ascending column to that table (date, id, whatever), and then order the query by that other column descendingly and limit the result to 1 row:

一点也不。您可以简单地向该表添加另一个升序列(日期,标识,等等),然后按顺序将该查询按其他列排序并将结果限制为1行:

SELECT v.version FROM version v ORDER by v.date DESC LIMIT 1;

This way you even get a history of when each version was reached.

这样,您甚至可以获得每个版本到达时间的历史记录。

Edit:

The above sql query wouldn't work on SQL Server since it doesn't support the LIMIT statement. One would have to circumvent that deficiency, possibly as described in this "All Things SQL Server" blog entry.

上面的SQL查询在SQL Server上不起作用,因为它不支持LIMIT语句。人们不得不规避这种不足,可能就像这篇“All Things SQL Server”博客文章中所描述的那样。

#5


Based on your comments to other responses, it seems that:

根据您对其他回复的评论,似乎:

  1. You don't want users to just modify the value.
  2. 您不希望用户只修改该值。

  3. You only ever want one value returned.
  4. 您只需要返回一个值。

  5. The value is static, and scripted.
  6. 值是静态的,并且是脚本化的。

So, might I suggest that you script a function that returns the static value? Since you'll have to script an update to the version number anyway, you'll simply drop and recreate the function in your script when you update the database.

那么,我可以建议您编写一个返回静态值的函数吗?由于您无论如何都必须编写版本号的更新脚本,因此您只需在更新数据库时删除并重新创建脚本中的函数。

This has the advantage of being usable from a view or a procedure, and since a function's return value is read-only, it can't be modified (without modifying the function).

这具有可从视图或过程使用的优点,并且由于函数的返回值是只读的,因此不能修改它(不修改函数)。

EDIT: You also wouldn't have to worry about convoluted solutions for keeping a table constrained to one row.

编辑:您也不必担心将表限制为一行的复杂解决方案。

Just a suggestion.

只是一个建议。

#6


Keeping a version number for the database makes total sense. However I prefer to have a Version table that can contain multiple rows with fields for the version number, the time the update occured and the user that performed the upgrade.

保留数据库的版本号是完全有道理的。但是,我更喜欢有一个Version表,它可以包含多行,其中包含版本号字段,更新发生的时间以及执行升级的用户。

That way you know which upgrade scripts have been run and can easily see if they have been run out of sequence.

这样您就可以知道哪些升级脚本已经运行,并且可以轻松查看它们是否已经不按顺序运行。

When you want to read the current version number you can just read the most recent record.

如果要读取当前版本号,只需阅读最新记录即可。

If you only store one record you have know way of knowing if a script has been missed out. If you want to be really clever you can put checks in you upgrade scripts so they won't run unless the previous version of the database is correct.

如果您只存储一条记录,则您知道如何错过脚本。如果您想要非常聪明,可以在升级脚本中加入检查,这样除非先前版本的数据库正确,否则它们将无法运行。

#7


By creating the one allowable original row as part of the database initialization script, and (also in that script) removing Insert permissions to that table for all logins (Only Updates will be allowed)

通过创建一个允许的原始行作为数据库初始化脚本的一部分,并且(也在该脚本中)删除对该表的所有登录的插入权限(仅允许更新)

You might also want to disallow deletes as well...

你可能也想要禁止删除...