Получение первичного ключа каждой строки внутри цикла в SQL Server 2005 - PullRequest
0 голосов
/ 13 февраля 2012

Я хочу написать триггер в SQL Server 2005, в котором внутри цикла я хочу обновить каждую строку конкретной таблицы на основе ее первичного ключа.Проблема в том, как мне получить первичный ключ каждой строки внутри цикла?

Пожалуйста, помогите

Извините, что не упомянул выше детали

  Table  UserPersonalInfo

   UserId       varchar(50) Primary Key                 
   FirstName    varchar(50)         
   MiddleName   varchar(50)         
   LastName         varchar(50)
   UserName         varchar(50)
   Password         varchar(50)
   ContactNo    bigint  
   Verified         bit 
   Address      varchar(100)    
   EmailId      varchar(100)    
   RoleId       int 
   CurrentFine  money   
   Photo        image   

   Table CurrentlyIssuedBook

   Userid   varchar(50) Primary Key
   BookId   varchar(50) 
   IssuedDate   datetime    
   ExpectedReturnDate   datetime    
   ISBN varchar(50) 

 Table CurrentDate

     date datetime

Выше две таблицы

Теперь то, что я пытаюсь сделать, это ...

Каждый раз, когда я запускаю свое приложение C #, я буду пытаться обновить дату в таблице CurrentDate с фактической текущей датой.Если обновление выполнено успешно, триггер запустится.

Внутри триггера я хочу обновить штраф для каждого пользователя в таблице UserPersonalInfo.Для этого я подумал об использовании цикла, но как получить значение первичного ключа каждой строки из таблицы UserInfo?

Моя логика точного расчета выглядит следующим образом

totalfine = 0
x =  currentdate - ExpectedReturnDate
y = x/30
z = x%30

for(int i=0; i <y; i++)
{
   totalfine = totalfine + (2^i * 4 * 30);
}

totalfine = totalfine + (2^i * 4 * z);

Теперь, пожалуйста, предложите мне, что мне делать?

Ответы [ 2 ]

2 голосов
/ 13 февраля 2012

Не можете ли вы сделать что-то вроде этого:

 CREATE TRIGGER tr_CurrentDateUpdate
   ON  CurrentDate
   AFTER UPDATE
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    UPDATE  UserInfo
    SET     fine = 6
    WHERE   userid like '%foo%'

    UPDATE  UserInfo
    SET     fine = 7
    WHERE   userid like '%baa%'

END
GO

Где предложения "где" - это ваши критерии выбора пользователей, которых вы хотите изменить, а штраф = ваши расчеты?

Кроме того, я не проверял это, но, если у вас есть свои вычисления в UDF, я думаю, вы могли бы просто поместить что-то вроде этого, где у меня были мои операторы обновления:

DECLARE @InsertedDate Datetime

SELECT  @InsertedDate = date
FROM inserted   

UPDATE  u
SET     u.fine = cf.FineResult
FROM    UserInfo u
cross apply dbo.CalculateFine(u.UserId, @InsertedDate) cf

Где CalculateFine UDF содержит логику о том, как преобразовать данные пользователя в их штраф.

С UDF примерно так:

 CREATE FUNCTION CalculateFine (@UserId varchar(50), @CurrentDate datetime)
 RETURNS money
 AS
 BEGIN

--TODO  get expected return date ExpectedReturnDate from CurrentlyIssuedBook for that @UserId

--TODO Do you need all these delcarations?
DECLARE @x AS INT
DECLARE @fine AS MONEY
DECLARE @y AS INT
DECLARE @z AS INT

SET @x = DATEDIFF(dd, @CurrentDate, ExpectedReturnDate)
SET @y = @x/30
SET @z = @x%30
-- TODO  convert your logic here....

--Return your answer
RETURN @fine
END
2 голосов
/ 13 февраля 2012

Не используйте цикл.

Вы можете обновить каждую строку в таблице, просто используя оператор update без предложения where, например:

declare @currentdate datetime
select @currentdate = date from currentdate

update userinfo
set fine = case when @currentdate < getdate() then 100 else 0 end

Конечно, я не знаю, каков ваш точный расчет, поэтому вышеприведенный пример является просто тривиальным.

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

declare @ID int
declare cur_loop cursor fast_forward for 
    select UserId from UserInfo

open cur_loop
fetch next from cur_loop into @ID
while @@FETCH_STATUS=0 begin
    -- your code here
    update UserInfo set fine = (calculation result) where UserID=@ID
    fetch next from cur_loop into @ID
end
close cur_loop
deallocate cur_loop
...