2009-07-14 5 views
4

У меня есть 2 процедуры. Один, который создает временную таблицу и другую (или несколько других), которые используют временную таблицу, созданную в первом proc. Это считается плохой формой? Я сейчас вхожу в существующую кодовую базу и много использует этот шаблон. Это, безусловно, беспокоит меня, но я не могу сказать, что это явно плохая идея. Я просто нахожу это раздражающим образцом - что-то пахнет гнилым, но я не могу сказать, что. Я бы предпочел бы построить таблицу локально, а затем заполнить ее с помощью exec. Но для этого требуются procs, которые возвращают только одну таблицу, что является необычным в существующей кодовой базе.делится временными таблицами между процедурами, считающимися плохой формой?

Разве гуру SQL уклоняются от такого рода обмена темпами? Если да, то почему? Я пытаюсь сформулировать мнение об этом и хотел бы внести свой вклад.

Будет ли перспектива жизнеспособной альтернативой?

Как насчет производительности? Было бы лучше построить @table локально или построить #table в "fill" proc?

Там хорошее обсуждение всех методов здесь: http://www.sommarskog.se/share_data.html

ответ

3

Как парадигма программирования это уродливо, потому что оно включает в себя передачу внеполосных параметров («параметры контекста»), которые явно не вызываются в сигнатурах процедуры. Это создает скрытые зависимости и приводит к эффекту спагетти.

Но в конкретном контексте SQL существует просто нет альтернативы. SQL работает с наборами данных, и вы не можете передавать эти данные в качестве параметров процедуры. У вас мало альтернатив:

  • Пройдите через клиента. Все слишком очевидно, что это не реальный вариант.
  • XML или строки с разделителями для представления результатов. Это не серьезный вариант на любом участке, они могут дать хорошую «программирующую» семантику (то есть Demeter Law соответствие), но они действительно действительно сосут, когда производительность вступает в игру.
  • общие таблицы (будь то в tempdb или в appdb), как предлагает Raj. Вы теряете автоматическое обслуживание #temp (очистка по количеству ссылок идет до 0), и вы должны быть готовы к созданию условий гонки. Кроме того, они могут расти большими без причины (они больше не разделяются сеансом в отдельные ряды, например, таблицы #temp).
  • @tables. Они привязаны к контексту декларации (т. Е. К процедуре) и не могут передаваться между процедурами. Я также обнаружил some nasty problems under memory pressure.
0

Я столкнулся с этим точно такой же проблемой. Что я могу сказать из личного опыта:

Если есть способ избежать использования таблицы #temp для нескольких процедур, используйте его. #temp-таблицы легко потерять и могут легко вырастить tempdb, если вы не будете осторожны.

В некоторых случаях этот метод не допускается (мой классический пример - это определенные функции отчетности, которые строят данные по-разному на основе конфигурации отчета). Если управлять осторожно, я считаю, что в этих ситуациях это приемлемо.

0

Совместное использование временных таблиц - неплохая идея. Но мы должны гарантировать, что данные уровня таблицы не должны обрабатываться двумя процессами одновременно, что приведет к сценарию Dirty Read/Write. Это также поможет иметь отдельную таблицу [централизованный] и обработчики, работающие над ней, для синхронизации данных. Что касается производительности, это правда, что с несколькими процессами, использующими одни и те же временные данные, будет снижаться производительность. Но в то же время наличие отдельных таблиц [на Proc] приведет к увеличению потребления памяти,

0

Я использовал этот подход в нескольких случаях. Но я всегда объявляю таблицу temp как полностью квалифицированную таблицу, а не используя #tablename.

CREATE TABLE [tempdb].[dbo].[tablename] 

При таком подходе легко отслеживать временную таблицу.

Радж

+1

не может ли эта таблица делиться между несколькими последующими вызовами «прочитанного» proc?кажется пятном, где вы увидите прерывистые и трудно отлаживаемые ошибки – jcollum

+0

Как это отличается от глобальной таблицы темп (## temp)? –

+0

## temp собирается упасть после того, как соединение, которое его создало, закрылось. – JeffO

1

Самая большая проблема с таблицами временных обмена является то, что он вводит внешних зависимостей в процедуру, которая не может быть очевидным на первый взгляд. Скажем, у вас есть процедура p1, которая вызывает процедуру p2, а временная таблица t1 используется для передачи информации между двумя процедурами. Если вы хотите запустить p2 изолированно, чтобы увидеть, что он делает, вам нужно создать «проводку», которая определяет # t1, прежде чем вы сможете ее запустить. Использование временных таблиц в T-SQL часто эквивалентно использованию глобальных переменных на других языках - не рекомендуется, но иногда неизбежно.

SQL Server 2008 теперь имеет табличные параметры, но Microsoft решила сделать их доступными только для чтения в этой версии. Тем не менее, это означает, что вам не нужно использовать временные таблицы в некоторых сценариях, где вам приходилось раньше.

Мой совет: используйте их, если вам нужно, но тщательно документируйте их использование.Если у вас есть часть proc, которая зависит от запуска таблицы temp, вызовите это в комментарии.

0

Другая техника, которую я видел, чтобы избежать использования временных таблиц, - это так называемые таблицы с «SPID-keyed». Вместо временной таблицы, можно определить регулярную таблицу со следующими свойствами:

CREATE TABLE spid_table 
(
    id INT IDENTITY(1, 1) NOT NULL, 
    -- Your columns here 
    spid INT NOT NULL DEFAULT @@SPID, 
    PRIMARY KEY (id) 
); 

В ваших процедур, вы бы код, подобный следующему:

SELECT @var = some_value 
FROM spid_table 
WHERE -- some condition 
AND spid = @@SPID; 

и в конце обработки:

DELETE FROM spid_table 
WHERE spid = @@SPID; 

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

0

Я думаю, это нормально, если 2-й прок проверяет наличие временной таблицы &, если это так. Кроме того, он может вызвать ошибку, если временная таблица не существует, попросив пользователя сначала запустить proc1.

Почему работа разделена на 2 хранимых процесса? Не может быть сделано в 1 proc?

+0

Это хороший вопрос, но я не могу ответить; кто-то где-то решил, что это либо хорошая идея, единственное решение или приемлемое. Затем он застрял. – jcollum

+0

Не может ли он быть объединен в процедуру? – shahkalpesh

1

Иногда это единственный способ пойти. Если вам нужно это сделать, то ДОКУМЕНТ, ДОКУМЕНТ, ДОКУМЕНТ фактов. Вот один из способов сделать это ясно, поставить определение таблицы в качестве комментария в разделе параметров ...

CREATE PROCEDURE xyz 
(
    @param1 int   --REQUIRED, what it does 
    ,@param2 char(1)  --OPTIONAL, what it does 
    ,@param3 varchar(25) --OPTIONAL, what it does 
    --this temp table is required and must be created in the calling procedure 
    --#TempXyz (RowID  int   not null primary key 
    --   ,DataValue varchar(10) not null 
    --   ,DateValue datetime  null 
    --  ) 
) 

Также документ в вызывающей процедуре, в которой создается таблица температуры ....

--** THIS TEMP TABLE IS PASSED BETWEEN STORED PROCEDURES ** 
--** ALL CHANGES MUST TAKE THIS INTO CONSIDERATION!!! ** 
CREATE TABLE #TempXyz 
(RowID  int   not null primary key 
,DataValue varchar(10) not null 
,DateValue datetime  null 
)