저장 프로 시저를 만들 때 테이블이 있어도 지연된 이름 확인을 강제 할 수 있습니까?


10

SQL Server에서 저장 프로 시저를 만들 때 존재하지 않는 테이블을 참조 할 수 있습니다. 그러나 테이블이 존재하는 경우 프로 시저에서 참조하는 모든 열이 해당 테이블에 있어야합니다 ( Deferred Name Resolution ).

존재 여부에 관계없이 프로 시저에서 참조 된 모든 테이블의 이름 확인을 연기하도록 SQL Server에 지시 할 수 있습니까? 일반적인 구문 검사를 유지하고 싶기 때문에 가능하더라도 저장 프로 시저 정의를 시스템 테이블에 해킹하는 것은 옵션이 아닙니다.

내가이가 보일 수 있습니다 할 묻는 것으로 예상 조금 이상한 비트 I 자동차는 C #로 작성된 응용 프로그램에서 테이블 정의 및 저장 프로 시저를 생성하고 나 SQL의 요구와 변화를 주문 코드를 변경하는 것은 매우 어려운 일 : 그래서 여기에 몇 가지 배경입니다 그들. 내 코드는 스키마가 트랜잭션 내에서 일관성이 있다는 것을 "보증"하지만 현재는 테이블 열이 참조되는 저장 프로 시저를 정의하기 전에 테이블 열이 정의되어 있음을 보장 할 수 없습니다.

아래는 C #에 의해 생성 된 SQL의 정식 예입니다.

--Say this table already exists.
CREATE TABLE myTable
(
    a NVARCHAR(MAX)
)
GO

--My C# code creates something like this
BEGIN TRAN 
GO

--the stored procedure gets generated first.
CREATE PROCEDURE mySproc
AS
BEGIN
    SELECT a,b FROM myTable
END

--then the table update
ALTER TABLE myTable
    ADD b nvarchar(MAX)

COMMIT TRAN 

그것은 이다 나를 C # 코드에서이 문제를 해결하는 것이 가능하지만 간단한 "마술"나는 SQL에서 뽑을 수 조정할을 기대하고있다. 이렇게하면 많은 시간 이 절약됩니다 .


1
프로 시저를 작성 / 변경하기 전에 모든 스키마 변경을 처리 할 수 ​​없습니까? 테이블이 정확하기 전에 왜 절차가 존재해야합니까?
Aaron Bertrand

이제 코드에서 해당 옵션을 추구하고 있습니다. SQL이 생성되는 방식은 상당히 복잡하지만 (단순한 예 였지만) 생각했던 것처럼 PITA만큼 크지 않을 것 같습니다.
다니엘 제임스 Bryars

2
동적 SQL로 가득 찬 저장 프로 시저를 채워서 문제를 해결할 수는 있지만 스키마 변경을 처리하기 위해 스크립트를 생성하면 저장 프로 시저가 그렇게 어려울 것입니다. 지연된 이름 확인의 작동 방식을 나타내는 옵션이 너무 많지 않습니다. 내가 아는 책이나 적어도 그들이 흥미를 느끼고 싶은 것으로 추측 할 수있는 유일한 제안은 실제로 다른 방법입니다-좀 더 엄격하게 -sommarskog.se/strict_checks.html 참조 ).
Aaron Bertrand

동적 SQL에 대한 좋은 아이디어. 트리거, 인덱스, 뷰, 프로 시저 및 함수에 대해 동일한 문제가 있습니다. 그러나 코드를 변경하여 Tables, Indexes, Triggers, 함수, sprocs 만 변경했습니다.
다니엘 제임스 Bryars

나는 sommarskog의 제안을 좋아합니다. 버그를 피하는 데 확실히 도움이 될 것입니다. Strict 옵션을 구현 한 경우 테이블이 변경되어 기존 Sproc을 손상하는지 확인하기 위해 모든 "Strict ON"Sproc을 재평가 할 수도 있습니다. 분명히 "DDL에서 논리적 트랜잭션"이 필요합니다. 그런 다음 테이블과 프로 시저를 하나의 단위로 변경할 수 있습니다.
다니엘 제임스 Bryars

답변:


6

아니.

나는 그것을 타이핑하는 것만으로도 죄책감을 느끼지만 슬프게도 아닙니다. 이 유스 케이스에 대해 들어 본 것은 이번이 처음이며 완벽합니다. 요청을 제출하는 것이 가장 좋습니다.http://connect.microsoft.com 손자가 할 수 있습니다. ;-)


5

여전히 관심이있는 경우 사용할 수있는 해결 방법이 있습니다. 업데이트 된 코드는 다음과 같습니다.#deferResolution 프로 시저의 각 쿼리에 임시 테이블을 입니다. 임시 테이블은 런타임에만 존재하기 때문에 적절한 열이 아직없는 경우에도 프로 시저를 컴파일 할 수 있습니다 myTable.

심지어 동일한 실행 계획을 얻습니다 ( #deferResolution쿼리 옵티마이 저가이를 WHERE NOT EXISTS항상 참으로 평가 하는 방식으로 인해 프로 시저의 각 명령문에 대해 테이블 )을 얻을 수도 있습니다 .

그러나 이것은 지적 재산권을 위해 주로 제시되는 끔찍한 해킹이며 고장이 발생하는 경우가 있습니다. Aaron이 언급했듯이 모든 스키마 변경을 올바른 순서로 수행하는 것이 좋습니다.

--Say this table already exists.
CREATE TABLE myTable
(
    a NVARCHAR(MAX)
)
GO

--My C# code creates something like this
BEGIN TRAN 
GO

--the sproc gets generated first.
CREATE PROCEDURE mySproc
AS
BEGIN
    CREATE TABLE #deferResolution (dummy INT NOT NULL)
    SELECT a,b FROM myTable WHERE NOT EXISTS (SELECT * FROM #deferResolution WHERE 0=1)
END

--then the table update
ALTER TABLE myTable
    ADD b nvarchar(MAX)

COMMIT TRAN 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.