T-SQL을 통해 프로그래밍 방식으로 데이터베이스 참조


11

데이터베이스 이름을 인수로 사용하여 해당 데이터베이스의 인덱스 테이블과 조각화 수준을 반환하는 저장 프로 시저를 작성 중입니다. 이 저장 프로시 저는 DBA 데이터베이스 (DBA가 사물을 모니터링하고 최적화하는 데 사용하는 테이블이 포함 된 DB)에 있습니다. 차이가 있다면 문제의 시스템은 모두 SQL Server 2008 R2입니다.

기본 쿼리가 해결되었지만 인덱스의 실제 이름을 제공하려고 노력하고 있습니다. 내가 아는 한, 그 정보는 각 개인의 sys.indexes 뷰에 포함되어 있습니다. 내 특정 문제는 다른 데이터베이스의 저장 프로 시저에서 프로그래밍 방식으로 해당 뷰를 참조하려고합니다.

이를 설명하기 위해이 부분은 문제가되는 쿼리의 일부입니다.

FROM sys.dm_db_index_physical_stats(@db_id,NULL,NULL,NULL,NULL) p
INNER JOIN sys.indexes b ON p.[object_id] = b.[object_id] 
    AND p.index_id = b.index_id 
    AND b.index_id != 0

@db_id로 식별 된 데이터베이스에서 적절한 sys.indexes 뷰를 사용하고 있기 때문에 쿼리가 제대로 작동합니다. 그러나 DBA 데이터베이스에서 이것을 호출하려고하면 sys.indexes보기가 잘못된 데이터베이스에 대한 것이므로 모두 null이됩니다.

더 일반적인 용어로, 나는 다음과 같은 것을 할 수 있어야합니다.

DECLARE @db_name NVARCHAR(255) = 'my_database';
SELECT * FROM @db_name + '.sys.indexes';

또는

USE @db_name;

문자열 연결과 OBJECT_NAME / OBJECT_ID / DB_ID 함수의 조합을 사용하여 데이터베이스를 전환하거나 다른 데이터베이스를 참조하려고 시도했지만 아무것도 작동하지 않는 것 같습니다. 커뮤니티가 가질 수있는 아이디어에 대해 감사하지만 각 저장 데이터베이스에 상주하기 위해이 저장 프로 시저를 재구성해야한다고 생각합니다.

어떤 제안이라도 미리 감사드립니다.


1
의심되는 이것에 대해 동적 SQL을 사용해야합니다.
JNK

답변:


10

동적 SQL은 이러한 유형의 관리 작업에 유용합니다. 다음은 조각 모음 수준을 얻을뿐만 아니라 조각 모음을 수행하는 코드를 생성하는 저장 프로 시저의 스 니펫입니다.

select @SQL = 
'
select getdate(),
       ''' + @@ServerName + ''',
       ''' + @DatabaseName + ''',
       so.Name,
       si.Name,
       db_id(''' + @DatabaseName + '''),
       ips.object_id,
       ips.index_id,
       ips.index_type_desc,
       ips.alloc_unit_type_desc,
       ips.index_depth,
       ips.avg_fragmentation_in_percent,
       ips.fragment_count,
       avg_fragment_size_in_pages,
       ips.page_count,
       ips.record_count,
       case
         when ips.index_id = 0 then ''alter table [' + @DatabaseName + '].'' + ss.name + ''.['' + so.name + ''] rebuild with (online = on)''
         else ''alter index '' + si.name + '' on [' + @DatabaseName + '].'' + ss.name + ''.['' + so.name + ''] rebuild with (online = on)''
       end
  from sys.dm_db_index_physical_stats(db_id(''' + @DatabaseName + '''),null,null,null, ''' + @SampleMode + ''') ips
  join [' + @DatabaseName + '].sys.objects so  on so.object_id = ips.object_id
  join [' + @DatabaseName + '].sys.schemas ss  on ss.schema_id = so.schema_id
  join [' + @DatabaseName + '].sys.indexes si  on si.object_id = ips.object_id
                      and si.index_id  = ips.index_id
order by so.Name, ips.index_id
'

exec (@SQL)

JNK의 의견에 따라 동적 SQL을 사용하도록 쿼리를 변경했습니다. 물론 작동합니다. 조각 모음 코드를 생성하는 별도의 쿼리가 있습니다. 나는 이것을 실행하고 모양을 보여줄 것입니다. 그러나 이것을 대답으로 받아들입니다.
mdoyle

한 가지주의해야 할 사항은 SQL Server 2008R2 Enterprise Edition에서 실행됩니다. 표준 버전에서는 "(온라인 = 켜기)로 다시 작성"이 지원되지 않습니다.
datagod

1
Sweet, 나는 지금 당신의 대답을 찬성 투표 할 충분한 담당자가 있습니다. :-) 이것은 매끄러운 쿼리이지만 코드 생성 쿼리를 분리하는 것이 좋습니다. 결과를 텍스트로 실행하고 잘라 붙여 넣기 작업을 할 수있는 것을 좋아합니다. 매우 우아한 솔루션-모두 감사합니다!
mdoyle

8

동적 SQL의 대안 은 명령 행, 에이전트 작업 단계, Invoke-Sqlcmd Powershell cmdlet 에서 호출 하거나 SSMS 에서 활성화 할 수있는 SQLCMD 입니다. SQLCMD 구문의 예는 다음과 같습니다.

:SETVAR DatabaseName MyDatabase

SELECT * FROM $(DatabaseName).sys.indexes;

SQLCMD 모드는 내가 알고 싶었던 기능 중 하나입니다. 많은 상황에서 편리합니다.


1
PowerShell을 사용하면 매우 간단하고 우아합니다. 난 당신의 접근 방식을 좋아합니다, 마크 +1
Thomas Stringer

@Shark 좋은 점, Powershell cmdlet을 편집하겠습니다.
Mark Storey-Smith

또한 좋은 해결책입니다. 이것도 살펴볼 것입니다.
mdoyle

이것이 좋으며, 이것이 TSQL에서 지원되지 않는 좋은 이유가 있습니까?
tbone

0

일반적으로 다른 DB에 포함 된 프로 시저에서 하나의 테이블 세트를 참조하는 것은 어렵습니다. Master에서 프로 시저를 시스템 프로 시저로 설치하면 다시 참조하지 않고 다른 DB 컨텍스트에서 사용할 수 있습니다.

나는 당신의 절차가 'sp_'로 시작하면 보편적으로 보이고, 'sys.sp_ %'스키마에서 정의하면 다른 DB 컨텍스트에서 사용될 수 있다고 생각합니다.

이를 통해 DB_name을 동적으로 연결하지 않고도 여러 DB에서 작동 할 수있는 대체 방법을 제공 할 수 있습니다.

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