我在表格中有两个字段,Column1和Column2
Column1 | Column2
-------------------
F | B
A | C
--------------
B F needs prevention
C A needs prevention
如何在没有触发器的情况下阻止(B,F)和(C,A)插入?
答案 0 :(得分:1)
所以基本上你想要防止插入与你已经拥有的行完全相反。
一种方法是添加一个检查约束和一个唯一索引:
CREATE TABLE dbo.MyTable
(
Column1 char(1) NOT NULL,
Column2 char(1) NOT NULL,
CONSTRAINT chk_Col1AndCol2 CHECK(Column1 <= Column2)
);
GO
CREATE UNIQUE INDEX UX_MyTable
ON dbo.MyTable (Column1, Column2);
GO
此检查约束阻止Column1保存大于Column2中值的值。
如果您不想将column1限制为小于或等于column2, 另一种选择是使用具有用户定义功能的检查约束:
CREATE TABLE dbo.MyTable
(
Column1 char(1) NOT NULL,
Column2 char(1) NOT NULL
);
GO
CREATE UNIQUE INDEX UX_MyTable -- Again, same unique index
ON dbo.MyTable (Column1, Column2);
GO
CREATE FUNCTION fn_CheckMyTable
(
@Column1 char(1),
@Column2 char(1)
)
RETURNS int
AS
BEGIN
RETURN
(
SELECT COUNT(*)
FROM MyTable
WHERE Column1 = @Column2
AND Column2 = @Column1
)
END;
GO
ALTER TABLE MyTable
ADD CONSTRAINT chk_MyTable1 CHECK(dbo.fn_CheckMyTable(Column1, Column2) = 0);
GO
答案 1 :(得分:0)
您可以尝试使用以防止这种情况 check constraint
CREATE TABLE MY_TABLE (
COLUMN1 varchar(255) NOT NULL,
COLUMN2 varchar(255) NOT NULL,
CONSTRAINT MY_CONSTRAINT CHECK ((COLUMN1, COLUMN2) NOT IN (('B','F'), ('C','A')))
);
当然语法可能因提供商而异。
答案 2 :(得分:0)
您可以使用TRIGGER_NESTLEVEL
:
CREATE TABLE t(col1 CHAR(5), col2 CHAR(5));
CREATE TABLE t_helper(i CHAR(5));
CREATE TRIGGER trg_t_helper ON t_helper
AFTER INSERT
AS
BEGIN
INSERT INTO t(col1, col2)
SELECT i, 'B'
FROM inserted;
END;
CREATE TRIGGER trg_t ON t
AFTER INSERT
AS
BEGIN
IF ((SELECT TRIGGER_NESTLEVEL( OBJECT_ID('trg_t_helper'),'AFTER', 'DML'))= 0)
RAISERROR('Direct data insert are disabled.',16,-1);
END;
检查:
INSERT INTO t_helper(i) VALUES ('Z');
SELECT * FROM t;
--col1 col2
--Z B
INSERT INTO t(col1, col2) VALUES ('A', 'B');
Msg 50000 Level 16 State 1 Line 6
禁用直接数据插入。
<强> DBFiddle Demo 强>