PDA

View Full Version : کمک در مورد تریگر



tazarvmmr
سه شنبه 15 آذر 1390, 00:19 صبح
سلام به همه
دوستان من یک تریگر برای یک جدول نوشتم کدش دقیقا اینه:



Create trigger [dbo].[tr_AttachmentsUpdate]
On [dbo].Attachments
After Update

AS

Begin
Declare @Id int
Declare @LastLES int
Set @Id = (Select Id From Deleted)
Set @LastLES = (Select LES from Deleted)
if Update(LES) goto endsec
if Update(LET) goto endsec
if @LastLES = 1 goto endsec

Update Attachments
Set LES = 2, LET = convert(smalldatetime, getdate())
Where Id = @Id


endsec:
End
GO


خوب توضیح اینکه وقتی یک ردیف ویرایش بشه، مقادر فیلدهای LES و LET به روز میشن (البته بجز فیلدهای LES و LET) و اینطوری من میفهمم که کدوم ردیف و در چه زمانی تغییر داشته، این تریگر وقتی فقط یک ردیف آپدیت میشه درست کار میکنه ولی وقتی جندتا ردیف همزمان آپدیت میشن تریگر کار نمیکنه و پیام خطا میده
پیام خطا هم اینه:



Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.



کسی میدونه چه تغییری در تریگر باید بدم که بتونه در زمانی که چند ردیف جدول با هم دیگه تغییر میکنن درست کار کنه؟

ممنون میشم

یوسف زالی
چهارشنبه 16 آذر 1390, 21:12 عصر
سلام.
چند تا نکته:
وقتی از سلکت در پرانتز استفاده می کنید یعنی دقیقا خروجی اون سلکت فقط یک فیلد داره و فقط یک ردیف بر می گردونه. مشکل از اینجاست.
دوم اینکه دیدم goto دارید. استفاده از این دستور شان شما رو تا حد یک برنامه نویس خیلی مبتدی کاهش می ده.
به هیچ وجه در هیچ زبانی (منظورم زبان های سطح پایین مثل اسمبلی یا فرترن نیست) از این دستور استفاده نکنید.

tazarvmmr
چهارشنبه 16 آذر 1390, 22:13 عصر
سلام
از بابت توصیه در مورد Goto ممنونم، ولی اگر اجازه بدید راجع به مشکل اصلی یه کوچولو صحبت کنیم، فکر میکنید اگر این کد به این شکل تغییر کنه درست میشه؟

Update Attachments
Set LES = 2, LET = convert(smalldatetime, getdate())
Where Id = Deleted.Id


یا اینکه مثلا:


Update Attachments
Set LES = 2, LET = convert(smalldatetime, getdate())
Where Id in (Select Id From Deleted)



ممنون میشم تجربتون رو بهم بگید.

یوسف زالی
پنج شنبه 17 آذر 1390, 00:36 صبح
نمی دونم دارید چه کار می کنید اما کد دوم منطقی تره که می شه به این فرم هم نوشتش:
update Attachments Set LES = 2, LET = convert(smalldatetime, getdate()) from Deleted X where Attachments.ID = X.ID

tazarvmmr
پنج شنبه 17 آذر 1390, 01:03 صبح
من سعی میکنم براتون توضیح بدم
ببینید من به همه جداول بانک دو تا فیلد اضافه کردم، LES و LET
فیلد LES سه تا مقدار داره 0 و 1 و 2 ، وقتی یک ردیف جدید درج بشه توی جدول مقدار LES برابر 0 هست بصورت پیش فرض و مقدار LET ساعت و تاریخ سیستم هست، که در حقیقت نشون میده این ردیف در زمانی که در LET قید شده درج شده، این تریگر زمانی که هرکدوم از ردیفها ویرایش بشن اجرا میشه و مقدار LES رو برابر 2 قرار میده و دوباره LET زمان جاری رو میگیره به این شکل معلوم میشه که کدوم ردیفها در چه تاریخی درج شدند و در چه تاریخی ویرایش شدند، در جای دیگری وقتی رکوزدها توسط کاربران ارشد برنامه بررسی شد مقدار LES برابر 1 و مقدار LET مجددا برابر تاریخ بررسی قرارداده میشه. این تریگر باید در مورد ویرایش تمام فیلدهای کار کنه بجز زمانی که ویرایش روی خود فیلدهای LES و LET و توسط کاربر ارشد انجام میشه. هدف کلی این بوده که کاربران ارشد با اجرای یک sp بتونند بفهمند در جداول مورد نظرشان کدوم ردیفها تازه درج شدند و یا تازه ویرایش شدند و هنوز بررسی یا تایید نشدند.

امیدوارم با این توضیح متوجه شده باشید که منطق چی هست، این رو گفتم چون دوتا حالت بیشتر نداره، یا روش جالبی رو دارم برای این منظور اجرا میکنم و یا اینکه روش اصلا به درد بخور نیست! و راه بهتری وجود داره که من ازش بیخبرم! امیدوارم نظر شما رو هم بدونم در این مورد و با توجه به این منطق بتونید راهنماییم کنید.

ممنون

یوسف زالی
پنج شنبه 17 آذر 1390, 02:47 صبح
تا اینجا که نوشتنش سخت نیست. اما سوال:
تریگر بیچاره از کجا می فهمه کاربر یک مدیر هست یا یوزر عادی؟
فرض کنید مدیر بیاد خودش یک پست بزنه یا حتی پستی رو اصلاح کنه.
بهتره تمام این اتفاقات در SP مربوطه بیفته که هم خیلی آسون تره و هم اینکه درگیر کار با تریگر و مصائب اون نمی شید.
توصیه: استفاده از تریگر وقتی با SP می تونید کار کنید کار خوبی نیست.

tazarvmmr
پنج شنبه 17 آذر 1390, 05:38 صبح
خوب تریگر نمیفهمه! وقتی کاربر ارشد اینکارو میکنه بلافاصله sp تایید فراخوانی میشه از داخل برنامه.

tazarvmmr
پنج شنبه 17 آذر 1390, 17:14 عصر
باید بگم من کاملا متوجه شدم که باید چطوری تریگر رو تغییر بدم، برای اینکه شاید در آینده کسی شبیه همین سوال رو داشته باشه من اینجا مینوسیم که تریگر نهایی چی شد


Create trigger [dbo].[tr_AttachmentsUpdate]
On [dbo].Attachments
After Update

AS

Begin

if Update(LES) goto endsec
if Update(LET) goto endsec

Update Attachments
Set LES = 2, LET = convert(smalldatetime, getdate())
Where Id in (Select Id from Deleted)


endsec:

End

GO


البته شاید بشه بجای goto از return هم استفاده کرد که من امتحان نکردم.