How to configure a table column in TSQL that works

2019-07-29 22:42发布

问题:

I have a table that looks like this:

ID  A   B   Count
-----------------
1  abc  0   1
2  abc  0   2
3  abc  1   1
4  xyz  1   1
5  xyz  1   2
6  xyz  1   3
7  abc  1   2
8  abc  0   3

The "Count" column is incremented by one in the next insertion depending on the value of fields "A" and "B". so for example, if the next record I want to insert is:

ID  A   B   Count
-----------------
   abc  0

The value of count will be 4.

I have been trying to find documentation about this, but I'm still quite lost in the MS SQL world! There must be a way to configure the "Count" column as a sequence dependent on the other two columns. My alternative would be to select all the records with A=abc and B=0, get the maximum "Count", and do +1 in the latest one, but I suspect there must be another way related to properly defining the Count column when creating the table.

回答1:

The first question is: Why do you need this?

There is ROW_NUMBER() which will - provided the correct PARTITION BY in the OVER() clause - do this for you:

DECLARE @tbl TABLE(ID INT,A VARCHAR(10),B INT);
INSERT INTO @tbl VALUES
 (1,'abc',0)
,(2,'abc',0)
,(3,'abc',1)
,(4,'xyz',1)
,(5,'xyz',1)
,(6,'xyz',1)
,(7,'abc',1)
,(8,'abc',0);

SELECT *
      ,ROW_NUMBER() OVER(PARTITION BY A,B ORDER BY ID)
FROM @tbl
ORDER BY ID;

The problem is: What happens if a row is changed or deleted?

If you write this values into a persistant column and one row is removed physically, you'll have a gap. Okay, one can live with this... But if a value in A is changed from abc to xyz (same applies to B of course) the whole approach breaks.

If you still want to write this into a column you can use the ROW_NUMBER() from above to fill these values initially and a TRIGGER to set the next value with your SELECT MAX()+1 approach for new rows.

If the set of combinations is limited you might create a SEQUENCE (needs v2012+) for each.

But - to be honest - the whole issue smells a bit.