나는 마이크로 소프트 SQL 서버 2012에서 SQL CLR 트리거를 사용하여 DB 동기화 엔진을 만드는 오전이 트리거는 저장 프로 시저 또는 함수를 호출 (하여 삽입에 대한 접근 및 삭제 된 의사 테이블이 없습니다 @@ procid에 액세스 할 수는 없습니다. 참조SQL CLR 트리거 - 얻을 소스 테이블
차이 here.
이 "동기화 엔진은"테이블과 필드 맵이 동기화 작업이 무엇인지 결정하기 위해 매핑 테이블을 사용합니다. 대상 테이블과 필드를 (내 매핑 테이블에서) 확인하려면 트리거 자체에서 소스 테이블 이름을 가져와야합니다. Stack Overflow 및 다른 사이트에서이 문제를 해결할 수 없다는 많은 답변을 보았습니다.
잠재적 인 솔루션 :
using (SqlConnection lConnection = new SqlConnection(@"context connection=true")) {
SqlCommand cmd = new SqlCommand("SELECT object_name(resource_associated_entity_id) FROM sys.dm_tran_locks WHERE request_session_id = @@spid and resource_type = 'OBJECT'", lConnection);
cmd.CommandType = CommandType.Text;
var obj = cmd.ExecuteScalar();
}
이 사실 올바른 테이블 이름을 반환하지, 나는 단서를 제공 한 website을 발견했습니다.
질문 :
내 질문이 잠재적 인 솔루션이 어떻게 신뢰할 수 있습니까? @@ spid가 실제로이 단일 트리거 실행으로 제한됩니까? 아니면 다른 동시 트리거가이 프로세스 ID 내에서 중복 될 수 있습니까? 데이터베이스 내에서 동일한 트리거 및/또는 다른 트리거를 여러 번 실행할 수 있습니까? 이 사이트에서
, 그것은 이 보인다 이드 중복되지 않는 열려있는 연결로 제한 사실상 과정 : here, here 및 here. 이 내 소스 테이블을 얻을 수있는 안전한 방법이 될 것인가?왜?
저는 비슷한 질문을 한 것이지만 내 구체적인 상황 (그 중 하나만 제외하고는)에 대한 유효한 대답이 없습니다. 그 이유는 다음과 같습니다.
이 동기화 엔진은 단일 DB에서 작동하며 변경 사항을 대상 테이블에 적용하여 사용자 정의 데이터로 데이터를 변환 할 수 있습니다. 정의 변환 자동 소스 - 타겟 형 변환 및 분석, 심지어 같은 데이터를 변환하기위한 그 맵핑 테이블에 저장된 메소드를 실행하도록에서는 CSharpCodeProvider를 사용할 수있다. 그것은 이미 구축되었으며, 매우 견고하며 우리가하고있는 일에 대한 좋은 성과 척도를 가지고 있습니다. 지금은 1 허용을 구축하기 위해 노력하고있어 : n 및합니다 ('마스터'테이블로 동일한 ID를 필요로 확장 테이블을 포함한) 테이블 변경을 "genericise"코드를하려합니다. 이전에는 각 트리거에 하드 코딩 된 "목표 테이블"정의가 있었고 원본을 결정하기 위해 매핑 테이블을 사용하고있었습니다. 이제 원본 테이블을 가져 와서 매핑 테이블을 사용하여 모든 대상 테이블을 확인하고 싶습니다. 이것은 중간로드 환경에서 사용되며 CRUD 작업을 완료하기 위해 별도의 서버 프로세스가 선택하는 "Change Order Book"의 변경 사항을 푸시합니다.
코멘트에서 언급 한 바와 같이 편집
, 위의 쿼리는 매우 "불확실"입니다. syscolpars 또는 sysidxstats와 같은 시스템 개체를 반환하는 경우가 많습니다 (예 : SQL Server를 다시 시작한 후). 그러나 dm_tran_locks 테이블에는 항상 동일한 object_name을 가진 'RID'(Row ID)와 연관된 resource_type이있는 것으로 보입니다.지금까지 안정적으로 작동 나의 현재 쿼리는 다음과 같다 (만약이 변경을 업데이트하거나 높은 부하 테스트에서 작동하지 않습니다) :
select t1.ObjectName FROM (
SELECT object_name(resource_associated_entity_id) as ObjectName
FROM sys.dm_tran_locks WHERE resource_type = 'OBJECT' and request_session_id = @@spid
) t1 inner join (
SELECT OBJECT_NAME(partitions.OBJECT_ID) as ObjectName
FROM sys.dm_tran_locks
INNER JOIN sys.partitions ON partitions.hobt_id = dm_tran_locks.resource_associated_entity_id
WHERE resource_type = 'RID'
) t2 on t1.ObjectName = t2.ObjectName
을이 항상 그런 경우, 나는 그것을 발견 할 것이다 테스트 중.
이것은 적합합니다. 엔진이 정확히 하나의 객체, 즉 트리거가 실행하는 테이블에 잠금을 설정한다고 가정합니다. 어쩌면 그렇게 될 수도 있지만 항상 누군가가 당신에게 보증 할 것을 기대할 수는 없습니다. 나는'@@ spid'에 대해별로 염려하지 않을 것입니다. MARS는 둘 이상의 명령문이 연결에서 활성화 될 수있게하지만 이것은 가짜 동시성의 일종입니다. 트리거 실행은 겹치지 않으며 순차적으로 실행됩니다. 방해하는 다른 진술에 대해 걱정할 필요는 없습니다. –
특히'SERIALIZABLE' ('SELECT * FROM T WITH (HOLDLOCK)')에서 실행할 때 트랜잭션을 던질 때 어떤 일이 일어나는지 테스트하십시오. 다른 잠금이 이미있는 트랜잭션에서 트리거가 실행되면 어떻게됩니까? –
하나의 트리거 (또는 아마도 한 세트의 코드)를 하나 이상의 테이블에 대한 트리거로 사용하려고합니다. –