2013-04-15 2 views
0

Будет ли создание переменной в случае необходимости в хранимой процедуре или функции или триггере, помогает в оптимизации производительности? Какой из них лучше ниже или оба имеют одинаковые характеристики?Помогает ли создание переменной при необходимости?

Вариант 1:

CREATE TRIGGER [dbo].[UpdateAmount] ON [RequestDB].[dbo].[Invoice] 
AFTER UPDATE 
AS 
BEGIN 
IF UPDATE(Service_Amount) 
BEGIN 
    DECLARE @NewService_Amount float,@OldService_Amount float //Var Created When needed 
    SELECT @NewService_Amount = I.Service_Amount FROM INSERTED I 
    SELECT @OldService_Amount = D.Service_Amount FROM DELETED D 
    IF (@NewService_Amount <> @OldService_Amount) 
    BEGIN 
    SELECT @InvId = I.Id FROM INSERTED I 
    DECLARE @DiffService_Amount float //Var Created When needed 
    SET @DiffService_Amount = @NewService_Amount - @OldService_Amount 
    UPDATE [RequestDB].[dbo].[Request] SET Actual_Amount = @DiffService_Amount WHERE Invoice_Id = @InvId 
    END 
END 
END 

Вариант 2:

CREATE TRIGGER [dbo].[UpdateAmount] ON [RequestDB].[dbo].[Invoice] 
AFTER UPDATE 
AS 
BEGIN 
DECLARE @NewService_Amount float,@OldService_Amount [email protected]_Amount float //All Var Created at once on top of code 
IF UPDATE(Service_Amount) 
BEGIN 
    SELECT @NewService_Amount = I.Service_Amount FROM INSERTED I /*For New UPDATE Value: INSERTED. For Old BEFORE UPDATE Valie: DELETED*/ 
    SELECT @OldService_Amount = D.Service_Amount FROM DELETED D 
    IF (@NewService_Amount <> @OldService_Amount) 
    BEGIN 
    SELECT @InvId = I.Id FROM INSERTED I 
    SET @DiffService_Amount = @NewService_Amount - @OldService_Amount 
    UPDATE [RequestDB].[dbo].[Request] SET Actual_Amount = @DiffService_Amount WHERE Invoice_Id = @InvId 
    END 
END 
END 
+2

Вы могли бы хотеть прочитать об этом первым: http://www.jimmcleod.net/blog/index.php/2008/06/05/triggers -set-based-not-row-based/ – granadaCoder

+2

Согласовано с granadaCoder - поскольку оба неверны, если предположить, что 'вставленный' и' deleted' содержат одну строку, это не та область, в которой я бы сосредоточился. После того, как вы переключитесь на выполнение набора на основе 'UPDATE', вероятно, не будет никаких локальных переменных вообще. –

ответ

1

docs не слишком конкретно о других переменных чем сказать, что, как только оно объявлено, оно доступно через этот пакетный процесс:

Объем переменной зависит от того, что она объявлена ​​до конца партии или хранимой процедуры, в которой она объявлена.

Моего предположения будет объявить позже лучше (учитывая то, как они слово Документов) - если вы не используете его, избежать объявлений его. Однако, реальный ответ должен был бы проверить его и профилировать. Что лучше работает в практике будет настоящим решением, ИМХО.

Я также надеюсь, что это не преждевременная оптимизация. Если вы отказываетесь от декларации, чтобы ваши сценарии выполнялись быстрее, вы, вероятно, смотрите не в то место.

+0

Глядя в неправильном месте означает? Я не получаю ур. – Dhwani

+0

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

+0

Okie Got ur point ... – Dhwani

1

В вашем случае вы не можете выбирать между простыми переменными и переменными таблицы, поскольку триггеры SQL Server установлены на основе (см. Комментарии granadaCoder и Damien_The_Unbeliever). Это естественный подход по сравнению с подходом на основе строк (или по строкам, см. Триггеры MySQL).

Вы можете переписать этот триггер таким образом:

CREATE TRIGGER [dbo].[UpdateAmount] ON [RequestDB].[dbo].[Invoice] 
AFTER UPDATE 
AS 
BEGIN 
IF UPDATE(Service_Amount) 
BEGIN 
    DECLARE @SelectedInvoices TABLE (
     Invoice_Id INT PRIMARY KEY, 
     Actual_Amount FLOAT NULL 
    ); 
    INSERT INTO @SelectedInvoices (Invoice_Id, Actual_Amount) 
    SELECT new.Invoice_Id, new.Service_Amount - old.Service_Amount -- I assume that Service_Amount column is mandatory (NOT NULL) 
    FROM deleted AS old INNER JOIN inserted AS new ON old.Invoice_Id = new.Invoice_Id 
    WHERE old.Service_Amount <> new.Service_Amount -- I assume that Service_Amount column is mandatory (NOT NULL) 

    UPDATE [RequestDB].[dbo].[Request] 
    SET Actual_Amount = sel.Actual_Amount 
    FROM [RequestDB].[dbo].[Request] AS req INNER JOIN @SelectedInvoices AS sel ON req.Invoice_id = sel.Invoice_Id 
END 
END 
GO 
+0

Нет необходимости в проверке 'IF EXISTS', если вы собираетесь использовать таблицу в 'INNER JOIN' - если строк нет, то соединение все равно станет пустым. –

+0

@Damien_The_Unbeliever: Спасибо. –

+0

Спасибо за ур ответ. Что полезно мне, чтобы ясное представление о триггере. – Dhwani