当前位置: 首页 > 面试题库 >

如何确保理货台的连续性?

公羊俊德
2023-03-14
问题内容

在SQL ForSmarties中,JoeCelko提供了Series表(在其他地方称为Tally或Numbers)的ANSI SQL定义。他的定义确保列中的值从1到最大值都是唯一的,正的和连续的:

CREATE TABLE Series (
  seq INTEGER NOT NULL PRIMARY KEY,
  CONSTRAINT non_negative_nbr CHECK (seq > 0),
  CONSTRAINT numbers_are_complete CHECK ((SELECT COUNT(*) FROM Series) = (SELECT MAX(seq) FROM Series))
);

通过PRIMARY
KEY声明确保唯一性。约束确保了积极性non_negative_nbr。有了这两个约束,约束就可以确保连续性numbers_are_complete

SQL Server在检查约束中不支持子查询。当我尝试创建系列表时,出现如下错误:

Msg 1046, Level 15, State 1, Line 4
Subqueries are not allowed in this context. Only scalar expressions are allowed.
Msg 102, Level 15, State 1, Line 4
Incorrect syntax near ')'.

如果删除不支持的约束numbers_are_complete,则剩下以下定义:

CREATE TABLE Series (
  seq INTEGER NOT NULL PRIMARY KEY,
  CONSTRAINT non_negative_nbr CHECK (seq > 0)
);

当我尝试创建此版本的Series时,它会成功:

Command(s) completed successfully.

此版本的Series较弱,因为它不强制表中数字的连续性。

为了证明这一点,首先我必须填充表格。我采用了Itzik Ben-
Gan在他的文章“虚拟数字辅助表”中描述的技术,以有效地对65,536行执行此操作:

WITH
N0(_) AS (SELECT NULL UNION ALL SELECT NULL),
N1(_) AS (SELECT NULL FROM N0 AS L CROSS JOIN N0 AS R),
N2(_) AS (SELECT NULL FROM N1 AS L CROSS JOIN N1 AS R),
N3(_) AS (SELECT NULL FROM N2 AS L CROSS JOIN N2 AS R),
N4(_) AS (SELECT NULL FROM N3 AS L CROSS JOIN N3 AS R)
INSERT INTO Series (
  seq
)
SELECT
  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS n
FROM N4;

查询产生如下输出:

(65536 row(s) affected)

现在,我可以从这样的表中进行选择,以产生65,536行:

SELECT seq
FROM Series;

我已经截断了结果集,但它看起来像这样:

seq
1
2
...
65535
65536

自己检查一下,您会发现结果集中有[1,65536]区间中的每个数字。该系列是连续的。

但是我可以通过删除不是该范围端点的任何行来破坏连续性:

DELETE FROM Series
WHERE seq = 25788;

如果强制执行连续性,则此语句将引发错误,但它将成功:

(1 row(s) affected)

对于人类来说,通过目视检查来发现缺失值将是困难的。他们必须先怀疑某个值是否丢失,然后再去解决问题。出于这些原因,篡改Series数据是将依赖于Series表连续的SQL
Server应用程序中引入细微错误的简便方法。

假设用户编写了一个查询,该查询从Sequence读取以枚举来自另一个源的行。经过我的篡改之后,该查询现在将在某个值附近产生错误的结果-
到第25788行,一切都减少了一个。

可以编写查询来检测“序列”表中的缺失值,但是如何约束该表以使缺失值不可行?


问题答案:

我有三个潜在的建议:

(1)将您的数字表设为只读(例如,拒绝更新/插入/删除)。EVER,您为什么要从此表中删除?您的应用程序当然不应该这样做,您的用户也不应该手动进行操作。用户按下“此按钮的作用是什么?”时,不需要所有这些检查约束。按钮,则只需删除按钮即可。

DENY DELETE ON dbo.Serial TO [your_app_user];
-- repeat for individual users/roles

(2)更简单的方法是创建一个触发器而不是触发器来防止删除操作:

CREATE TRIGGER dbo.LeaveMyNumbersAlone
ON dbo.Serial
INSTEAD OF DELETE
AS
BEGIN
  SET NOCOUNT ON;
  RAISERROR('Please leave my numbers table alone.', 11, 1);
END

是的,这是可以克服的,但必须有人真正做到这一点。而且,如果您雇用的人可能会这样做,并通过对数据库的通用访问权来信任他们,请祈祷这是他们计划造成的最大损失。

是的,如果您删除/重新创建数字表或在其他地方实现它,您可能会忘记重新实现触发器。但是您也可能会忘记手动解决差距的任何操作。

(3)如果您愿意随时获取数字,则可以完全避免使用数字表。我为此使用sys.all_columns和sys.all_objects之类的目录视图,具体取决于我需要多少个数字:

;WITH n AS (SELECT TOP (10000) n FROM 
  (SELECT n = ROW_NUMBER() OVER
    (ORDER BY s1.[object_id])
    FROM sys.all_objects AS s1
    CROSS JOIN sys.all_objects AS s2
  ) AS x ORDER BY n
)
SELECT n FROM n ORDER BY n; -- look ma, no gaps!

如果只需要100行,则可以只使用其中一个视图而无需交叉联接。如果需要更多,可以添加更多视图。不试图将您从数字表中移开,但这可以解决一些局限性,例如(a)在每个实例上构建数字表,以及(b)在哲学上反对这种事情的人(我在我的书中遇到过很多职业)。



 类似资料:
  • 让我们假设一个关于护士名册的变体示例,在该示例中,护士不是在一天内分配一个班次,而是在当天分配一个可变数量的时间块(由24个时间块组成)。例如:Nurse1被分配给时间块[8、9、10、11、12、13、14]。让我们把这些连续的赋值称为ShiftPeriod。在这些移位周期上有一个硬的最小值和最大值。然而optaplanner很难找到一个可行的解决方案。 当有严格的连续约束时,是否更好地将规划实

  • 问题内容: 我想知道如何使方法在后台运行。即。该方法在程序启动时启动,并继续执行其语句,直到关闭程序为止。对于前。可以说我有一个“ gravity()”方法,该方法在程序运行时会连续减小某个值。现在,我使用以下程序尝试了此操作,其中,当没有按下任何键时,我试图将公爵拉下(重力)。但没有发生。 谢谢。 问题答案: 以最简单的方式,您可能会遇到以下情况: 编辑 添加了带有Swing Worker的示例

  • 问题内容: 可以在连续流上使用吗? 我的意思是说是一条命令,但在输出中仅保留我感兴趣的行。 我已经尝试过了,但是似乎只能在完成后才能执行,也就是说永远不会执行。 问题答案: 使用BSD grep(FreeBSD,Mac OS X等)时,打开的行缓冲模式。 您无需为GNU grep(几乎在任何Linux上使用)执行此操作,因为它会默认刷新(对于其他类似Unix的版本,如SmartOS,AIX或QNX

  • 现在,我有三个函数:updateFieldFromCollection1()、

  • 问题内容: (现已失效)页面http://stream.twitter.com/1/statuses/sample.json用于返回连续无休止的JSON数据流。 我想在自己的网页中使用jQuery(或JavaScript,但最好是jQuery)对其进行处理,以便能够基于实时推文显示视觉效果。 据我所知,jQuery 函数仅在服务器发送完所有数据后才执行回调函数,但这实际上是连续的数据流。我如何“按

  • 问题内容: 我想处理对象中的列表。我必须确保处理所有元素,以便收到它们。 因此l,我应该使用它吗? 还是只要不使用并行性就足以使用流? 问题答案: 你在问错问题。你正在询问而要按顺序处理项目,因此你必须询问订购。如果你有顺序的流并执行保证维持顺序的操作,则该流是并行处理还是顺序处理都没有关系;实施将维持秩序。 有序属性不同于并行与顺序。例如,如果你调用一个同时调用流将是无序在List返回的有序流。