我想创建一个表来容纳以下类型的数据
+--------+-----+----------+
| pk | ctr | name |
+--------+-----+----------+
| fish | 1 | herring |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----_+----------+
PK是主键字符串(100),不为null ctr是我要为每条pk行自动加1的字段
我尝试了以下
create or replace table schema.animals (
pk string(100) not null primary key,
ctr integer not null default ( select NVL(max(ctr),0) + 1 from schema.animals )
name string (1000) not null);
这产生了以下错误
SQL编译错误:第52位聚合函数的错误行6 不允许作为默认值规范的一部分 条款。
所以我应该像这样使用自动增量/ identity属性
AUTOINCREMENT | IDENTITY [ ( start_num , step_num ) | START num INCREMENT num ]
但它似乎无法支持每个唯一pk的重置
正在寻找有关如何解决此问题的建议,谢谢您的提前帮助
答案 0 :(得分:0)
您无法使用IDENTITY
方法执行此操作。建议的解决方案是使用INSTEAD OF
触发器,该触发器将在ctr
表的每一行上计算INSERTED
的值。例如
CREATE TABLE dbo.animals (
pk nvarchar(100) NOT NULL,
ctr integer NOT NULL,
name nvarchar(1000) NOT NULL,
CONSTRAINT PK_animals PRIMARY KEY (pk, ctr)
)
GO
CREATE TRIGGER dbo.animals_before_insert ON dbo.animals INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO animals (pk, ctr, name)
SELECT
i.pk,
(ROW_NUMBER() OVER (PARTITION BY i.pk ORDER BY i.name) + ISNULL(a.max_ctr, 0)) AS ctr,
i.name
FROM inserted i
LEFT JOIN (SELECT pk, MAX(ctr) AS max_ctr FROM dbo.animals GROUP BY pk) a
ON i.pk = a.pk;
END
GO
INSERT INTO dbo.animals (pk, name) VALUES
('fish' , 'herring'),
('mammal' , 'dog'),
('mammal' , 'cat'),
('mammal' , 'whale'),
('bird' , 'pengui'),
('bird' , 'ostrich');
SELECT * FROM dbo.animals;
结果
pk ctr name
------- ----- ---------
bird 1 ostrich
bird 2 pengui
fish 1 herring
mammal 1 cat
mammal 2 dog
mammal 3 whale
另一种方法是将标量用户定义的函数用作DEFAULT值,但它很慢:触发器在所有行上触发一次,而在每一行上调用该函数。
答案 1 :(得分:0)
我不知道您为什么会有一个名为pk
的列,该列不是 主键。您不能(轻松)做您想做的事。我建议这样做:
create or replace table schema.animals (
animal_id int identity primary key,
name string(100) not null primary key,
);
create view schema.v_animals as
select a.*, row_number() over (partition by name order by animal_id) as ctr
from schema.animals a;
也就是说,在需要使用ctr
而不是将其存储在表中时进行计算。