2017-02-08 5 views
0

Для моих модульных тестов SQL Server я пытаюсь отключить возврат всех строк при подсчете результатов " получить все хранимые процедуры. С этой целью я пытаюсь записать результаты в таблицу temp.T-SQL: размещение результатов хранимой процедуры в таблице temp, когда у вас есть столбец timestamp, и не может указывать имена столбцов

Я начинаю со связанной записи сервера, указывающей на текущий сервер и базу данных.

IF NOT EXISTS (SELECT * FROM sys.servers WHERE NAME = 'DB_LOCAL') 
BEGIN 
    DECLARE @DBNAME VARCHAR(MAX) = (SELECT DB_NAME()) 
    EXEC sp_addlinkedserver @server = 'DB_LOCAL', @srvproduct = '', @provider = 'SQLOLEDB', @datasrc = @@servername, @[email protected] 
END 

Это так, что я могу использовать OPENQUERY создать временную таблицу с выходной структуры хранимой процедуры на лету, без необходимости жесткого кода столбцов.

IF OBJECT_ID('tempdb..#ut_results') IS NOT NULL 
    DROP TABLE #ut_results 

SELECT * 
INTO #ut_results 
FROM OPENQUERY (DB_LOCAL, 'EXEC p_AnzLookup_get @id = 0') 

Я хочу использовать эту временную таблицу для EXEC моих сохраненных проков в, я не могу использовать OPENQUERY снова, потому что мне нужно указать переменные, как часть теста. Кроме того, модульный тест выполняется в транзакции, и это создает проблемы с блокировкой. Как только у меня есть структура, я это делаю. Я не могу указать имена столбцов без столбца timestamp, который, как мне кажется, будет работать, поскольку они могут быть изменены сторонними сторонами.

TRUNCATE TABLE #ut_results 

INSERT INTO #ut_results 
    EXEC p_AnzLookup_get @id = @record_id 

Эта вставка не работает, потому что у меня есть метка времени, возвращаемая хранимой процедурой.

Msg 273, Level 16, State 1, Line 2
Невозможно вставить явное значение в столбец временной метки. Используйте INSERT со списком столбцов, чтобы исключить столбец timestamp или вставить DEFAULT в столбец timestamp.

Из-за этой ошибки я не могу изменить столбец timestamp в таблице темп.

ALTER TABLE #ut_results 
    ALTER COLUMN TStamp BINARY(8) 

Msg 4928, Level 16, State 1, Line 5
Невозможно изменить столбец 'TSTAMP', потому что это 'метка времени'.

Я не могу сбросить и воссоздать столбец timestamp в таблице temp, поскольку он изменяет порядок столбцов.

ALTER TABLE #ut_results DROP COLUMN TStamp 
ALTER TABLE #ut_results ADD TStamp BINARY(8) 

Это приводит к различным ошибкам, когда данные вставки в неправильные колонки:

Msg 257, уровень 16, состояние 3, процедура p_AnzLookup_get, строка 20
неявное преобразование из типа данных DateTime в целое не допускается. Используйте функцию CONVERT для запуска этого запроса.

Я не могу вносить изменения в хранимые процедуры, для которых выполняются эти модульные тесты, и я не могу жестко закодировать имена столбцов. Мне нужно написать это таким образом, чтобы он был устойчивым и реагировал на изменения вне моего контроля.

Это всего лишь небольшое подмножество одного из модульных тестов, которое я извлек, чтобы продемонстрировать эту проблему. Любые мысли о том, как я обойду этот липкий бит?

ответ

0

У меня есть что-то, что сработает. Создайте временную таблицу, используя OPENQUERY, затем запишите ее через XML, чтобы получить список имен столбцов csv в varchar.Затем замените это, чтобы нанести столбец timestamp как varbinary (8).

Используя список столбцов из вышеизложенного, я могу выбрать структуру моей первой временной таблицы во второй с полями в правильном порядке и столбцом временной метки, определенным как varbinary (8), который может принимать данные временной метки.

Оно не очень Тхо:

IF OBJECT_ID('tempdb..#ut_results') IS NOT NULL DROP TABLE #ut_results 
IF OBJECT_ID('tempdb..#ut_results2') IS NOT NULL DROP TABLE #ut_results2 

SELECT * INTO #ut_results2 
FROM OPENQUERY (DB_LOCAL ,'EXEC p_AnzLookup_get @id=-1') 


DECLARE @cols VARCHAR(MAX) = '' 
SELECT @cols = Stuff((select ',' + name from tempdb.sys.columns where object_id = 
         object_id('tempdb..#ut_results2') 
         FOR XML PATH(''), TYPE      
        ).value('.', 'NVARCHAR(MAX)') 
        , 1, 1, '') 
SET @cols = REPLACE(@cols,'TStamp','CAST(TStamp AS VARBINARY(8)) AS TStamp') 

DECLARE @SQl VARCHAR(MAX) = 'SELECT ' + @cols + ' INTO #ut_results FROM #ut_results2 WHERE 1=2' 
EXEC (@SQl) 

IF OBJECT_ID('tempdb..#ut_results2') IS NOT NULL DROP TABLE #ut_results2 

EDIT: Одно небольшое изменение к этому. В приведенном выше примере я создаю последнюю таблицу temp в динамическом SQL, но после этого она не была доступна. Я изменил это на обычную таблицу.

DECLARE @SQl VARCHAR(MAX) = 'SELECT ' + @cols + ' INTO ut_results FROM #ut_results2' 
EXECUTE (@SQl)