Question

In SQL For Smarties, Joe Celko provides an ANSI SQL definition of a Series table (elsewhere called Tally or Numbers). His definition ensures the values in the column are unique, positive and contiguous from 1 up to the maximum value:

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))
);

Uniqueness is ensured by the PRIMARY KEY declaration. Positivity is ensured by the constraint non_negative_nbr. With these two constraints in place, contiguity is ensured by the constraint numbers_are_complete.

SQL Server does not support subqueries in check constraints. When I try to create the Series table, I receive an error like this:

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 ')'.

If I remove the unsupported constraint numbers_are_complete, I'm left with this definition:

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

When I try to create this version of Series, it succeeds:

Command(s) completed successfully.

This version of Series is weaker because it doesn't enforce contiguity of the numbers in the table.

To demonstrate this, first I have to populate the table. I have adapted a technique described by Itzik Ben-Gan in his article 'Virtual Auxiliary Table of Numbers' to do this efficiently for 65,536 rows:

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;

The query produces output like this:

(65536 row(s) affected)

Now I can select from the table like this to produce 65,536 rows:

SELECT seq
FROM Series;

I've truncated the result set, but it looks like this:

seq
1
2
...
65535
65536

Check it for yourself, and you'll see that every number in the interval [1, 65536] is in the result set. The series is contiguous.

But I can break contiguity by deleting any row that is not an endpoint of the range:

DELETE FROM Series
WHERE seq = 25788;

If contiguity were enforced, this statement would raise an error, but instead it succeeds:

(1 row(s) affected)

It would be difficult for a human to find the missing value by visual inspection. They would have to suspect that a value were missing in the first place before going to the trouble. For these reasons, tampering with the Series data is an easy way to introduce subtle bugs into an SQL Server application that relies on the Series table being contiguous.

Assume a user has written a query that reads from Sequence to enumerate rows from another source. After my tampering, that query would now produce incorrect results around a certain value - by the 25,788th row, everything is off by one.

It is possible to write a query to detect missing values in the Series table, but how do I constrain the table so that missing values are impossble?

Was it helpful?

Solution

I have three potential suggestions:


(1) Make your numbers table read-only (e.g. deny update/insert/delete). Why would you be deleting from this table, EVER? Your app certainly shouldn't be doing it, and your users shouldn't be able to manually do so either. No need for all these check constraints for users pressing the "what does this button do?" button, when you can simply remove the button.

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

(2) Even easier would be to create an instead of trigger to prevent deletes in the first place:

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

Yes, this can be defeated, but someone has to really go out of their way to do it. And if you're employing folks that are likely to do this, and trusting them with generic access to the database, pray that this is the most damage they're planning to do.

And yes, you might forget to re-implement the trigger if you drop / re-create the numbers table or implement it somewhere else. But you might also forget anything you might manually do to deal with gaps anyway.


(3) You can avoid a numbers table altogether if you're willing to derive numbers on the fly. I use catalog views like sys.all_columns and sys.all_objects for this, depending on how many numbers I need:

;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!

If you only need 100 rows, you can just use one of the views without the cross join; if you need more, you can add more views. Not trying to push you away from a numbers table but this gets you around limitations such as (a) building a numbers table on every single instance and (b) people who are philosophically opposed to such a thing (I have come across many in my career).


As an aside, this really should be in the product. Please vote and state real business use cases in the following Connect item:

http://connect.microsoft.com/SQLServer/feedback/details/258733/add-a-built-in-table-of-numbers

OTHER TIPS

One way of solving this problem is to replace the table with a view.

This view definition is based on the same article referenced in the question and produces up to 65,536 unique, positive, and contiguous rows:

CREATE VIEW SeriesView
AS
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)
SELECT
    ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS seq
FROM N4;

In this way, the row numbers are always generated at query time by the ROW_NUMBER function. The set of values output by the ROW_NUMBER functon is contiguous, and every value is unique and positive.

If you try to delete from the view:

DELETE FROM SeriesView
WHERE seq = 25788;

The server will raise an error because the view is not updatable:

Msg 4406, Level 16, State 1, Line 1
Update or insert of view or function 'SeriesView' failed because it 

contains a derived or constant field.

I have not compared the performance of this technique compared to storing the values in a table. Both seem fast enough in practice, though I admit I've yet to use the view in production.

Performance-tuning of queries that select from Series is probably going to be more difficult because of the large execution plan generated by simply selecting from the view.

Simply compare the lengths of these execution plans to compare their apparent complexity:

This is the execution plan generated by selecting from the table in the question:

<?xml version="1.0" encoding="utf-16"?>
<ShowPlanXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.1.1" Build="10.0.5500.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
    <BatchSequence>
        <Batch>
            <Statements>
                <StmtSimple StatementCompId="1" StatementEstRows="65535" StatementId="1" StatementOptmLevel="TRIVIAL" StatementSubTreeCost="0.153148" StatementText="SELECT seq&#xD;&#xA;FROM Series;" StatementType="SELECT" QueryHash="0x5765DD2692E59AB9" QueryPlanHash="0x598E82F24F85C8B9">
                    <StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
                    <QueryPlan DegreeOfParallelism="1" CachedPlanSize="8" CompileTime="0" CompileCPU="0" CompileMemory="80">
                        <RelOp AvgRowSize="11" EstimateCPU="0.0722455" EstimateIO="0.0809028" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="65535" LogicalOp="Clustered Index Scan" NodeId="0" Parallel="false" PhysicalOp="Clustered Index Scan" EstimatedTotalSubtreeCost="0.153148" TableCardinality="65535">
                            <OutputList>
                                <ColumnReference Database="[tempdb]" Schema="[dbo]" Table="[Series]" Column="seq" />
                            </OutputList>
                            <RunTimeInformation>
                                <RunTimeCountersPerThread Thread="0" ActualRows="65535" ActualEndOfScans="1" ActualExecutions="1" />
                            </RunTimeInformation>
                            <IndexScan Ordered="false" ForcedIndex="false" NoExpandHint="false">
                                <DefinedValues>
                                    <DefinedValue>
                                        <ColumnReference Database="[tempdb]" Schema="[dbo]" Table="[Series]" Column="seq" />
                                    </DefinedValue>
                                </DefinedValues>
                                <Object Database="[tempdb]" Schema="[dbo]" Table="[Series]" Index="[PK__Series__DDDFBCBE0F975522]" IndexKind="Clustered" />
                            </IndexScan>
                        </RelOp>
                    </QueryPlan>
                </StmtSimple>
            </Statements>
        </Batch>
    </BatchSequence>
</ShowPlanXML>

This is the execution plan generated by selecting from the view in my answer:

<?xml version="1.0" encoding="utf-16"?>
<ShowPlanXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.1.1" Build="10.0.5500.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
    <BatchSequence>
        <Batch>
            <Statements>
                <StmtSimple StatementCompId="1" StatementEstRows="65536" StatementId="1" StatementOptmLevel="FULL" StatementOptmEarlyAbortReason="TimeOut" StatementSubTreeCost="0.692044" StatementText="SELECT seq&#xD;&#xA;FROM SeriesView;" StatementType="SELECT" QueryHash="0xD7D3DE2C825E3F56" QueryPlanHash="0x927D671566369AAC">
                    <StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
                    <QueryPlan DegreeOfParallelism="1" CachedPlanSize="32" CompileTime="6" CompileCPU="6" CompileMemory="680">
                        <RelOp AvgRowSize="15" EstimateCPU="0.00524288" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="65536" LogicalOp="Compute Scalar" NodeId="0" Parallel="false" PhysicalOp="Sequence Project" EstimatedTotalSubtreeCost="0.692044">
                            <OutputList>
                                <ColumnReference Column="Expr1065" />
                            </OutputList>
                            <RunTimeInformation>
                                <RunTimeCountersPerThread Thread="0" ActualRows="65536" ActualEndOfScans="1" ActualExecutions="1" />
                            </RunTimeInformation>
                            <SequenceProject>
                                <DefinedValues>
                                    <DefinedValue>
                                        <ColumnReference Column="Expr1065" />
                                        <ScalarOperator ScalarString="row_number">
                                            <Sequence FunctionName="row_number" />
                                        </ScalarOperator>
                                    </DefinedValue>
                                </DefinedValues>
                                <RelOp AvgRowSize="15" EstimateCPU="0.00131072" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="65536" LogicalOp="Segment" NodeId="1" Parallel="false" PhysicalOp="Segment" EstimatedTotalSubtreeCost="0.686801">
                                    <OutputList>
                                        <ColumnReference Column="Expr1064" />
                                        <ColumnReference Column="Segment1066" />
                                    </OutputList>
                                    <RunTimeInformation>
                                        <RunTimeCountersPerThread Thread="0" ActualRows="65536" ActualEndOfScans="1" ActualExecutions="1" />
                                    </RunTimeInformation>
                                    <Segment>
                                        <GroupBy />
                                        <SegmentColumn>
                                            <ColumnReference Column="Segment1066" />
                                        </SegmentColumn>
                                        <RelOp AvgRowSize="11" EstimateCPU="0.0065536" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="65536" LogicalOp="Compute Scalar" NodeId="2" Parallel="false" PhysicalOp="Compute Scalar" EstimatedTotalSubtreeCost="0.68549">
                                            <OutputList>
                                                <ColumnReference Column="Expr1064" />
                                            </OutputList>
                                            <ComputeScalar>
                                                <DefinedValues>
                                                    <DefinedValue>
                                                        <ColumnReference Column="Expr1064" />
                                                        <ScalarOperator ScalarString="NULL">
                                                            <Const ConstValue="NULL" />
                                                        </ScalarOperator>
                                                    </DefinedValue>
                                                </DefinedValues>
                                                <RelOp AvgRowSize="9" EstimateCPU="0.27394" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="65536" LogicalOp="Inner Join" NodeId="3" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.678937">
                                                    <OutputList />
                                                    <Warnings NoJoinPredicate="true" />
                                                    <RunTimeInformation>
                                                        <RunTimeCountersPerThread Thread="0" ActualRows="65536" ActualEndOfScans="1" ActualExecutions="1" />
                                                    </RunTimeInformation>
                                                    <NestedLoops Optimized="false">
                                                        <RelOp AvgRowSize="9" EstimateCPU="0.13697" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="32768" LogicalOp="Inner Join" NodeId="4" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.33946">
                                                            <OutputList />
                                                            <Warnings NoJoinPredicate="true" />
                                                            <RunTimeInformation>
                                                                <RunTimeCountersPerThread Thread="0" ActualRows="32768" ActualEndOfScans="1" ActualExecutions="1" />
                                                            </RunTimeInformation>
                                                            <NestedLoops Optimized="false">
                                                                <RelOp AvgRowSize="9" EstimateCPU="0.0684851" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="16384" LogicalOp="Inner Join" NodeId="5" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.169722">
                                                                    <OutputList />
                                                                    <Warnings NoJoinPredicate="true" />
                                                                    <RunTimeInformation>
                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="16384" ActualEndOfScans="1" ActualExecutions="1" />
                                                                    </RunTimeInformation>
                                                                    <NestedLoops Optimized="false">
                                                                        <RelOp AvgRowSize="9" EstimateCPU="0.0342426" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="8192" LogicalOp="Inner Join" NodeId="6" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.0848524">
                                                                            <OutputList />
                                                                            <Warnings NoJoinPredicate="true" />
                                                                            <RunTimeInformation>
                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="8192" ActualEndOfScans="1" ActualExecutions="1" />
                                                                            </RunTimeInformation>
                                                                            <NestedLoops Optimized="false">
                                                                                <RelOp AvgRowSize="9" EstimateCPU="0.0171213" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="4096" LogicalOp="Inner Join" NodeId="7" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.0424177">
                                                                                    <OutputList />
                                                                                    <Warnings NoJoinPredicate="true" />
                                                                                    <RunTimeInformation>
                                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="4096" ActualEndOfScans="1" ActualExecutions="1" />
                                                                                    </RunTimeInformation>
                                                                                    <NestedLoops Optimized="false">
                                                                                        <RelOp AvgRowSize="9" EstimateCPU="0.00856064" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="2048" LogicalOp="Inner Join" NodeId="8" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.0212003">
                                                                                            <OutputList />
                                                                                            <Warnings NoJoinPredicate="true" />
                                                                                            <RunTimeInformation>
                                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="2048" ActualEndOfScans="1" ActualExecutions="1" />
                                                                                            </RunTimeInformation>
                                                                                            <NestedLoops Optimized="false">
                                                                                                <RelOp AvgRowSize="9" EstimateCPU="0.00428032" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="1024" LogicalOp="Inner Join" NodeId="9" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.0105915">
                                                                                                    <OutputList />
                                                                                                    <Warnings NoJoinPredicate="true" />
                                                                                                    <RunTimeInformation>
                                                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="1024" ActualEndOfScans="1" ActualExecutions="1" />
                                                                                                    </RunTimeInformation>
                                                                                                    <NestedLoops Optimized="false">
                                                                                                        <RelOp AvgRowSize="9" EstimateCPU="0.00214016" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="512" LogicalOp="Inner Join" NodeId="10" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.00528701">
                                                                                                            <OutputList />
                                                                                                            <Warnings NoJoinPredicate="true" />
                                                                                                            <RunTimeInformation>
                                                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="512" ActualEndOfScans="1" ActualExecutions="1" />
                                                                                                            </RunTimeInformation>
                                                                                                            <NestedLoops Optimized="false">
                                                                                                                <RelOp AvgRowSize="9" EstimateCPU="0.00107008" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="256" LogicalOp="Inner Join" NodeId="11" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.0026347">
                                                                                                                    <OutputList />
                                                                                                                    <Warnings NoJoinPredicate="true" />
                                                                                                                    <RunTimeInformation>
                                                                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="256" ActualEndOfScans="1" ActualExecutions="1" />
                                                                                                                    </RunTimeInformation>
                                                                                                                    <NestedLoops Optimized="false">
                                                                                                                        <RelOp AvgRowSize="9" EstimateCPU="0.00053504" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="128" LogicalOp="Inner Join" NodeId="12" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.00130846">
                                                                                                                            <OutputList />
                                                                                                                            <Warnings NoJoinPredicate="true" />
                                                                                                                            <RunTimeInformation>
                                                                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="128" ActualEndOfScans="1" ActualExecutions="1" />
                                                                                                                            </RunTimeInformation>
                                                                                                                            <NestedLoops Optimized="false">
                                                                                                                                <RelOp AvgRowSize="9" EstimateCPU="0.00026752" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="64" LogicalOp="Inner Join" NodeId="13" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.000645262">
                                                                                                                                    <OutputList />
                                                                                                                                    <Warnings NoJoinPredicate="true" />
                                                                                                                                    <RunTimeInformation>
                                                                                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="64" ActualEndOfScans="1" ActualExecutions="1" />
                                                                                                                                    </RunTimeInformation>
                                                                                                                                    <NestedLoops Optimized="false">
                                                                                                                                        <RelOp AvgRowSize="9" EstimateCPU="0.00013376" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="32" LogicalOp="Inner Join" NodeId="14" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.000313585">
                                                                                                                                            <OutputList />
                                                                                                                                            <Warnings NoJoinPredicate="true" />
                                                                                                                                            <RunTimeInformation>
                                                                                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="32" ActualEndOfScans="1" ActualExecutions="1" />
                                                                                                                                            </RunTimeInformation>
                                                                                                                                            <NestedLoops Optimized="false">
                                                                                                                                                <RelOp AvgRowSize="9" EstimateCPU="6.688E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="16" LogicalOp="Inner Join" NodeId="15" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.000147668">
                                                                                                                                                    <OutputList />
                                                                                                                                                    <Warnings NoJoinPredicate="true" />
                                                                                                                                                    <RunTimeInformation>
                                                                                                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="16" ActualEndOfScans="1" ActualExecutions="1" />
                                                                                                                                                    </RunTimeInformation>
                                                                                                                                                    <NestedLoops Optimized="false">
                                                                                                                                                        <RelOp AvgRowSize="9" EstimateCPU="3.344E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="8" LogicalOp="Inner Join" NodeId="16" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="6.4631E-05">
                                                                                                                                                            <OutputList />
                                                                                                                                                            <Warnings NoJoinPredicate="true" />
                                                                                                                                                            <RunTimeInformation>
                                                                                                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="8" ActualEndOfScans="1" ActualExecutions="1" />
                                                                                                                                                            </RunTimeInformation>
                                                                                                                                                            <NestedLoops Optimized="false">
                                                                                                                                                                <RelOp AvgRowSize="9" EstimateCPU="1.672E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="4" LogicalOp="Inner Join" NodeId="17" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="2.3034E-05">
                                                                                                                                                                    <OutputList />
                                                                                                                                                                    <Warnings NoJoinPredicate="true" />
                                                                                                                                                                    <RunTimeInformation>
                                                                                                                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="4" ActualEndOfScans="1" ActualExecutions="1" />
                                                                                                                                                                    </RunTimeInformation>
                                                                                                                                                                    <NestedLoops Optimized="false">
                                                                                                                                                                        <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="2" LogicalOp="Constant Scan" NodeId="18" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="2.157E-06">
                                                                                                                                                                            <OutputList />
                                                                                                                                                                            <RunTimeInformation>
                                                                                                                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="2" ActualEndOfScans="1" ActualExecutions="1" />
                                                                                                                                                                            </RunTimeInformation>
                                                                                                                                                                            <ConstantScan />
                                                                                                                                                                        </RelOp>
                                                                                                                                                                        <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="1" EstimateRows="2" LogicalOp="Constant Scan" NodeId="19" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="4.157E-06">
                                                                                                                                                                            <OutputList />
                                                                                                                                                                            <RunTimeInformation>
                                                                                                                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="4" ActualEndOfScans="2" ActualExecutions="2" />
                                                                                                                                                                            </RunTimeInformation>
                                                                                                                                                                            <ConstantScan />
                                                                                                                                                                        </RelOp>
                                                                                                                                                                    </NestedLoops>
                                                                                                                                                                </RelOp>
                                                                                                                                                                <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="1" EstimateRows="2" LogicalOp="Constant Scan" NodeId="20" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="4.157E-06">
                                                                                                                                                                    <OutputList />
                                                                                                                                                                    <RunTimeInformation>
                                                                                                                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="8" ActualEndOfScans="4" ActualExecutions="4" />
                                                                                                                                                                    </RunTimeInformation>
                                                                                                                                                                    <ConstantScan />
                                                                                                                                                                </RelOp>
                                                                                                                                                            </NestedLoops>
                                                                                                                                                        </RelOp>
                                                                                                                                                        <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="1" EstimateRows="2" LogicalOp="Constant Scan" NodeId="21" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="4.157E-06">
                                                                                                                                                            <OutputList />
                                                                                                                                                            <RunTimeInformation>
                                                                                                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="16" ActualEndOfScans="8" ActualExecutions="8" />
                                                                                                                                                            </RunTimeInformation>
                                                                                                                                                            <ConstantScan />
                                                                                                                                                        </RelOp>
                                                                                                                                                    </NestedLoops>
                                                                                                                                                </RelOp>
                                                                                                                                                <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="15" EstimateRows="2" LogicalOp="Constant Scan" NodeId="22" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="3.2157E-05">
                                                                                                                                                    <OutputList />
                                                                                                                                                    <RunTimeInformation>
                                                                                                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="32" ActualEndOfScans="16" ActualExecutions="16" />
                                                                                                                                                    </RunTimeInformation>
                                                                                                                                                    <ConstantScan />
                                                                                                                                                </RelOp>
                                                                                                                                            </NestedLoops>
                                                                                                                                        </RelOp>
                                                                                                                                        <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="15" EstimateRows="2" LogicalOp="Constant Scan" NodeId="23" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="3.2157E-05">
                                                                                                                                            <OutputList />
                                                                                                                                            <RunTimeInformation>
                                                                                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="64" ActualEndOfScans="32" ActualExecutions="32" />
                                                                                                                                            </RunTimeInformation>
                                                                                                                                            <ConstantScan />
                                                                                                                                        </RelOp>
                                                                                                                                    </NestedLoops>
                                                                                                                                </RelOp>
                                                                                                                                <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="15" EstimateRows="2" LogicalOp="Constant Scan" NodeId="24" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="3.2157E-05">
                                                                                                                                    <OutputList />
                                                                                                                                    <RunTimeInformation>
                                                                                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="128" ActualEndOfScans="64" ActualExecutions="64" />
                                                                                                                                    </RunTimeInformation>
                                                                                                                                    <ConstantScan />
                                                                                                                                </RelOp>
                                                                                                                            </NestedLoops>
                                                                                                                        </RelOp>
                                                                                                                        <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="15" EstimateRows="2" LogicalOp="Constant Scan" NodeId="25" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="3.2157E-05">
                                                                                                                            <OutputList />
                                                                                                                            <RunTimeInformation>
                                                                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="256" ActualEndOfScans="128" ActualExecutions="128" />
                                                                                                                            </RunTimeInformation>
                                                                                                                            <ConstantScan />
                                                                                                                        </RelOp>
                                                                                                                    </NestedLoops>
                                                                                                                </RelOp>
                                                                                                                <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="255" EstimateRows="2" LogicalOp="Constant Scan" NodeId="26" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="0.000512157">
                                                                                                                    <OutputList />
                                                                                                                    <RunTimeInformation>
                                                                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="512" ActualEndOfScans="256" ActualExecutions="256" />
                                                                                                                    </RunTimeInformation>
                                                                                                                    <ConstantScan />
                                                                                                                </RelOp>
                                                                                                            </NestedLoops>
                                                                                                        </RelOp>
                                                                                                        <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="255" EstimateRows="2" LogicalOp="Constant Scan" NodeId="27" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="0.000512157">
                                                                                                            <OutputList />
                                                                                                            <RunTimeInformation>
                                                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="1024" ActualEndOfScans="512" ActualExecutions="512" />
                                                                                                            </RunTimeInformation>
                                                                                                            <ConstantScan />
                                                                                                        </RelOp>
                                                                                                    </NestedLoops>
                                                                                                </RelOp>
                                                                                                <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="255" EstimateRows="2" LogicalOp="Constant Scan" NodeId="28" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="0.000512157">
                                                                                                    <OutputList />
                                                                                                    <RunTimeInformation>
                                                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="2048" ActualEndOfScans="1024" ActualExecutions="1024" />
                                                                                                    </RunTimeInformation>
                                                                                                    <ConstantScan />
                                                                                                </RelOp>
                                                                                            </NestedLoops>
                                                                                        </RelOp>
                                                                                        <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="255" EstimateRows="2" LogicalOp="Constant Scan" NodeId="29" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="0.000512157">
                                                                                            <OutputList />
                                                                                            <RunTimeInformation>
                                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="4096" ActualEndOfScans="2048" ActualExecutions="2048" />
                                                                                            </RunTimeInformation>
                                                                                            <ConstantScan />
                                                                                        </RelOp>
                                                                                    </NestedLoops>
                                                                                </RelOp>
                                                                                <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="4095" EstimateRows="2" LogicalOp="Constant Scan" NodeId="30" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="0.00819216">
                                                                                    <OutputList />
                                                                                    <RunTimeInformation>
                                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="8192" ActualEndOfScans="4096" ActualExecutions="4096" />
                                                                                    </RunTimeInformation>
                                                                                    <ConstantScan />
                                                                                </RelOp>
                                                                            </NestedLoops>
                                                                        </RelOp>
                                                                        <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="4095" EstimateRows="2" LogicalOp="Constant Scan" NodeId="31" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="0.00819216">
                                                                            <OutputList />
                                                                            <RunTimeInformation>
                                                                                <RunTimeCountersPerThread Thread="0" ActualRows="16384" ActualEndOfScans="8192" ActualExecutions="8192" />
                                                                            </RunTimeInformation>
                                                                            <ConstantScan />
                                                                        </RelOp>
                                                                    </NestedLoops>
                                                                </RelOp>
                                                                <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="4095" EstimateRows="2" LogicalOp="Constant Scan" NodeId="32" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="0.00819216">
                                                                    <OutputList />
                                                                    <RunTimeInformation>
                                                                        <RunTimeCountersPerThread Thread="0" ActualRows="32768" ActualEndOfScans="16384" ActualExecutions="16384" />
                                                                    </RunTimeInformation>
                                                                    <ConstantScan />
                                                                </RelOp>
                                                            </NestedLoops>
                                                        </RelOp>
                                                        <RelOp AvgRowSize="9" EstimateCPU="2.157E-06" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="4095" EstimateRows="2" LogicalOp="Constant Scan" NodeId="33" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="0.00819216">
                                                            <OutputList />
                                                            <RunTimeInformation>
                                                                <RunTimeCountersPerThread Thread="0" ActualRows="65536" ActualEndOfScans="32768" ActualExecutions="32768" />
                                                            </RunTimeInformation>
                                                            <ConstantScan />
                                                        </RelOp>
                                                    </NestedLoops>
                                                </RelOp>
                                            </ComputeScalar>
                                        </RelOp>
                                    </Segment>
                                </RelOp>
                            </SequenceProject>
                        </RelOp>
                    </QueryPlan>
                </StmtSimple>
            </Statements>
        </Batch>
    </BatchSequence>
</ShowPlanXML>

The second is much larger because of the many cross joins.

Move your numbers_are_complete constraint query into in INSERT/UPDATE/DELETE trigger instead, and you should have no problems.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top