2009-10-25 5 views
5

새 소프트웨어를 개발하는 동안 기존 데이터베이스를 변경하고 있습니다. 작업을 계속하는 데 필요한 데이터베이스를 사용하여 기존 소프트웨어의 꽤 많은도있다, 즉, 나는 기존의 데이터베이스 테이블, 발동 등을 유지하고 싶은대체 업데이트 기본 키 트리거 및 업데이트

현재 내가 가지고있는 테이블

 
CREATE TABLE dbo.t_station (
    tx_station_id  VARCHAR(4) NOT NULL, 
    tx_description  NVARCHAR(max) NOT NULL, 
    tx_station_type  CHAR(1)  NOT NULL, 
    tx_current_order_num VARCHAR(20) NOT NULL, 

    PRIMARY KEY (tx_station_id) 
) 

Plant (생산 설비)를 참조하고 tx_current_order_num을 다른 테이블로 이동시키는이 테이블에 새로운 필드를 포함시켜야합니다. 왜냐하면 모든 행에 필요하지 않기 때문입니다. 그래서 만든 새 테이블 : - 내가보기에 dbo.t_station 테이블을 변경하고 트리거 대신 제공하기로 결정 그래서 지금

 
CREATE TABLE Private.Plant (
    PlantCode INT   NOT NULL, 
    Description NVARCHAR(max) NOT NULL, 

    PRIMARY KEY (PlantCode) 
) 
CREATE TABLE Private.Station (
    StationId VARCHAR(4) NOT NULL, 
    Description NVARCHAR(max) NOT NULL, 
    StationType CHAR(1)  NOT NULL, 
    PlantCode INT   NOT NULL, 

    PRIMARY KEY (StationId), 

    FOREIGN KEY (PlantCode) REFERENCES Private.Plant (PlantCode) 
) 
CREATE TABLE Private.StationOrder (
    StationId VARCHAR(4) NOT NULL, 
    OrderNumber VARCHAR(20) NOT NULL, 

    PRIMARY KEY (StationId) 
) 

, 나는 두 장소에서 동일한 데이터를 가지고 싶지 않아 DELETE, INSERT 및 UPDATE를 수행하십시오. 나는 그들에게 [대부분의] 문제가 없다.

제 질문은 INSTEAD OF UPDATE 트리거에 대한 기본 키 열 (tx_station_id) 업데이트 및 여러 행의 업데이트에 관한 것입니다.

트리거 블록 내부에 삽입 및 삭제 된 [psuedo] 테이블을 조인 할 수있는 방법이 있습니까?이를 통해 '기본 키 업데이트 전'과 '기본 키 업데이트 후'를 알 수 있습니까? 기본 키 열이 업데이트되면이 단계에서 이런 식으로 뭔가 ...

 
UPDATE sta 
    SET sta.StationId = ins.tx_station_id 
    FROM Private.Station AS sta 
     INNER JOIN deleted AS del 
      INNER JOIN inserted AS ins 
       ON ROW_IDENTITY_OF(del) = ROW_IDENTITY_OF(ins) 
      ON del.tx_station_id = sta.StationId 

나는 업데이트를 롤백 트리거 블록에 체크를 넣어 한 하나 개 이상의 행이 삽입 또는 삭제에있다 , 테이블.

+1

나는 누군가가 더 좋은 대답을 가지기를 바랐다. 이 문제는 과거에도 나에게 화를 냈다. –

답변

3

짧은 대답은 아니오입니다.

대리 키를 Private.Station에두고보기를 통해 그 키를 표시하고 이전 값과 이후 값을 식별하는 데 사용할 수 있습니다. 기본 키 또는 외래 키 관계를 변경할 필요는 없지만 뷰를 통해 업데이트 할 수없는 크래프트를 노출시켜 의사 테이블에 표시해야합니다. 예 :

alter table Private.Station add StationSk int identity(1,1) not null 

SELECT *를 사용하면 기존 응용 프로그램이 손상 될 수 있습니다. INSERT 문을 명시 적 삽입 열 목록없이, 그래야합니다. 그

짧은이있다 OVER ROW_NUMBER() (NULLIF (StationId, StationId) BY ORDER)를 사용하면 두에 가입 할 것 같은 것을 INSERTED와 DELETED, 사이에 문서화되지 않은 & 일관성을 주문 할 수있다,하지만 난 좋겠 길을 택하는 것을 주저하지 않으면 안됩니다. 매우, 주저.

캐스케이드 업데이트를 의도적으로 사용하지 않았습니까? 기본 키 값을 업데이트 할 수있을 때 유용합니다. 예 :

CREATE TABLE Private.Station (
    StationId VARCHAR(4) NOT NULL, 
    Description NVARCHAR(max) NOT NULL, 
    StationType CHAR(1)  NOT NULL, 
    PlantCode INT   NOT NULL, 
    PRIMARY KEY (StationId), 
    FOREIGN KEY (PlantCode) REFERENCES Private.Plant (PlantCode) 
     ON UPDATE CASCADE 
     -- maybe this too: 
     -- ON DELETE CASCADE 
) 

누군가 더 좋은 속임수가있을 수 있습니다. 기다려 봐!

+0

예, 대리 키 아이디어에 대해 생각했지만 테이블 이름과 열을 정확하게 보존하려고했습니다. 계단식 업데이트 및 삭제에 대한 내 주요 관심사에 대해 작동하지 않습니다. StationId는 데이터베이스 전체에서 참조되며 참조 테이블이 올바른 논리적 스테이션을 계속 참조하는지 확인하려고합니다. – Kepboy

+0

필자는 단 한 줄의 솔루션에 전혀 만족하지 않는다는 것을 지적해야한다. – Kepboy

+0

현재 스키마에서 t_station.tx_station_id에 대한 업데이트가 허용됩니까? 그렇지 않으면 COLUMNS_UPDATED()로 업데이트를 테스트하고 롤백하고 변경 사항을 감지하면 오류를 발생시킵니다. –

관련 문제