PDA

View Full Version : دستورات متفاوت برای updateو delete در یک trigger



Leyla2011
پنج شنبه 11 خرداد 1391, 06:04 صبح
سلام دوستان

من یه تریگر روی یکی از جدولهام دارم که در موقع update وdelete فیلد مربوط به موجودی کم وزیاد میشه

سوال اصلی این است که چطور توی یک تریگر مشخص کنم اگه update است از موجودی کم بشه اگه deleteاست به موجودی اضافه بشه؟


با این وصف که برای یک جدول نمیتونیم 2 تا تریگر همزمان داشته باشیم ، لطفا راهنمایی کنید

این هم کد مربوط به تریگر update که درست کار میکنه فقط میخوام delete رو هم توی این بیارم چی کار باید بکنم؟


USE [mydb]
GO
/****** Object: Trigger [dbo].[UpdateTrigt02onlineShop] Script Date: 05/30/2012 14:30:34 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER trigger [dbo].[UpdateTrigt02onlineShop]
on [dbo].[t02OnlineShop]
for Insert,update
as
begin
declare @OnlineShopId int,@OnlineShopDetailId int ,@Tafsili1Id int,
@Value int,@Tafsili3Id int,@Tafsili2Id int

SELECT @OnlineShopId=Id,@Tafsili1Id=Tafsili1Id
from inserted
DECLARE _Cursor CURSOR FOR
SELECT dbo.t02OnlineShopDetail.Id, dbo.t02OnlineShopDetail.Tafsili2Id,
dbo.t02OnlineShopDetail.Value, dbo.t02OnlineShop.Tafsili3Id
FROM dbo.t02OnlineShopDetail INNER JOIN
dbo.t02OnlineShop ON dbo.t02OnlineShopDetail.OnlineShopId = dbo.t02OnlineShop.Id
WHERE (dbo.t02OnlineShopDetail.OnlineShopId = @OnlineShopId)

OPEN _Cursor;


FETCH NEXT FROM _Cursor into @OnlineShopDetailId,@Tafsili2Id,@Value,@Tafsili3Id ;
WHILE @@FETCH_STATUS = 0
BEGIN
update t02StoreInventory set Value=Value-@Value
where Tafsili2Id=@Tafsili2Id and Tafsili3Id=@Tafsili3Id;
FETCH NEXT FROM _Cursor into @OnlineShopDetailId,@Tafsili2Id,@Value,@Tafsili3Id ;
END;
CLOSE _Cursor;
DEALLOCATE _Cursor;
end

tiphooo
پنج شنبه 11 خرداد 1391, 06:21 صبح
در قسمت for Insert,update
Delete را هم اضافه کن
و همانطور که برای درج متغیر @OnlineShopId تعریف کرده ای یک متغیر دیگر مثلا با نام @OnlineShopId1 برای حذف تعریف کن
و بعد از دستور
SELECT @OnlineShopId=Id,@Tafsili1Id=Tafsili1Id
from inserted
دستورات را برای Delete اضافه کن
SELECT @OnlineShopId1=Id,@Tafsili1Id1=Tafsili1Id
from deleted
حالا یک شرط بگذار که هرکدام که مقدار Null داشت دستورات مربوط به آن یکی را اجرا کند
IF @OnlineShopId1 Is Null
کدهای مربوط به Insert,Update
Else
کدهای مربوط به حذف
شاید این ساده ترین راه باشد
و شاید دوستان راه حل بهتری پیشنهاد کنند

UnlimitedPower
پنج شنبه 11 خرداد 1391, 06:46 صبح
سلام
می تونید چند تریگر با کدهای مختلف تعریف کنید.
تریگر برای delete را جدا و تریگر برای update را هم جدا.
فقط باید دقت کنید همدیگه رو خنثی نکنن.

Leyla2011
پنج شنبه 11 خرداد 1391, 09:02 صبح
در قسمت for Insert,update
Delete را هم اضافه کن
و همانطور که برای درج متغیر @OnlineShopId تعریف کرده ای یک متغیر دیگر مثلا با نام @OnlineShopId1 برای حذف تعریف کن
و بعد از دستور
SELECT @OnlineShopId=Id,@Tafsili1Id=Tafsili1Id
from inserted
دستورات را برای Delete اضافه کن
SELECT @OnlineShopId1=Id,@Tafsili1Id1=Tafsili1Id
from deleted
حالا یک شرط بگذار که هرکدام که مقدار Null داشت دستورات مربوط به آن یکی را اجرا کند
IF @OnlineShopId1 Is Null
کدهای مربوط به Insert,Update
Else
کدهای مربوط به حذف
شاید این ساده ترین راه باشد
و شاید دوستان راه حل بهتری پیشنهاد کنند

نه دوست گرامی با این کار به نتیجه می‌رسیم من امتحان کردم حتی موقع updateدستورات مربوط به deleteاجرا میشه

حمیدرضاصادقیان
پنج شنبه 11 خرداد 1391, 12:00 عصر
سلام.
پیشنهاد من این هست که اینکارو درون یک SP انجام بدید و هنگام حذف یا بروز کردن دیتابیس در داخل یک Transaction اینکارو بکنید.
اینکار از لحاظ Performance روی دیتابیس شما تاثیر زیادی خواهد داشت.
در ضمن اینکار شما تاثیر زیادی روی Performance خواهد گذاشت به خاطر استفاده از Cursor درداخل Trigger. شما میتونید این دستور رو با روشهای دیگه عوض کنید و شاهد سرعت بیشتری باشید.
شخصا خودم برای بروز رسانی انبار یک SP نوشتم که روی یک میلیون رکورد انبار با 1 میلیون فاکتور خرید و فروش و مرجوعی و... حدود 2 ثانیه طول میکشه. و برای حذف و اضافه نیز به جای Trigger از SP استفاده کرده و به محض اینکه رکوردی اضافه یا حذف میشه در داخل یک Transaction این بروز رسانی رو انجام میدم.چون در یک فاکتور که بیش از 200 قلم معمولا ثبت نمیکنند و بروز کردن مقدار 200 رکورد خیلی زمان کمی میبره و نیازی به استفاده از Cursor نیست.

tiphooo
پنج شنبه 11 خرداد 1391, 16:38 عصر
جای شرطها را عوض کنید درست می شود
و اینکه Update شما باید کنترل شده باشد و برای هر تغییری Update صورت نگیرد و با گذاشتن شرط UPDATED(نام فیلد) در صورتی که فیلد مورد نظر تغییر کرد Update اجرا شود
if @OnlineShopId Is NOT Null
دستورات مربوط به insert,Update (کنترل Updated اینجا چک شود)
else if @OnlineShopId1 Is Not Null
کدهای مربوط به delete

حمیدرضاصادقیان
پنج شنبه 11 خرداد 1391, 17:41 عصر
البته این نکته رو هم درنظر بگیرید که وقتی شما دارید عملیات Update انجام میدید هر دو جدول Deleted , Inserted تحت تاثیر قرار خواهند گرفت زیرا رکورد مربوطه اول حذف شده و مجددا اضافه خواهد شد که نتیجه آن در هردو جدول قرار میگیرد.

Leyla2011
پنج شنبه 11 خرداد 1391, 18:37 عصر
جای شرطها را عوض کنید درست می شود
و اینکه Update شما باید کنترل شده باشد و برای هر تغییری Update صورت نگیرد و با گذاشتن شرط UPDATED(نام فیلد) در صورتی که فیلد مورد نظر تغییر کرد Update اجرا شود
if @OnlineShopId Is NOT Null
دستورات مربوط به insert,Update (کنترل Updated اینجا چک شود)
else if @OnlineShopId1 Is Not Null
کدهای مربوط به delete
بله همینطور که آقای صادقیان گفتند هر دو جدول تحت تاثیر قرار میگیره و نتیجه دلخواه را نمیده :ناراحت:

حمیدرضاصادقیان
پنج شنبه 11 خرداد 1391, 23:24 عصر
درنهایت پیشنهاد بنده استفاده غیر از Trigger هست. البته در بعضی از طراحی هایی که مشاوره دادم بعضا مشاهده کردم که موجودی رو به صورت runtime محاسبه میکنند که به هیچ وجه این مورد رو نمی پسندم چون سربار اضافی زیادی روی سیستم تحمیل میکنه.ولی وقتی به صورت یک فیلد در دیتابیس ذخیره بشه بایک sp میتونید به نتیجه دلخواه برسید و از شر Trigger نیز خلاص خواهید شد.

hossein_h62
چهارشنبه 10 مهر 1392, 07:44 صبح
سلام دوستان من يه سوال دارم من با زبان سي شارپ برنامه نوشتم و از نسخه sql expressبراي پايگاه استفاده كردم بعد از تريگر استفاده كردم براي اينكه تغييرات اطلاعاتم رو ردگيري كنم حالا سوالم اينجاست كه چطور مي تونم در برنامه تريگر رو فراخواني كنم (اصلا چنين كاري امكان پذير هست) و بدونم چه كاربري در چه زماني برنامه رو تغيير داده يعني ميخوام مدير كه هيچي از پايگاه نميدونه توي يه فرمي به اطلاعاتي كه ديگر كاربران تغيير دادند دسترسي داشته باشه (اطلاعات جدول هاي deleted , inserted)اگه لطف كنيد كمكم كنيد ممنون ميشم در ضمن ارتباط با linq هستش
با تشكر
سلام
سوالتون رو باید در تاپیک جداگانه ای ایجاد می کردید؛
تریگر نیازی به فراخوانی نداره، با توجه به رویدادی که در تعریف تریگر مشخص میکنیم تریگر بصورت خودکار اجرا خواهد شد.

sarahjoon
چهارشنبه 10 مهر 1392, 11:12 صبح
ممنون من ميخوام كه بعد از اجراي تريگر به اطلاعات inserted , deleted دسترسي داشته باشم كه راهش اين هست كه اطلاعات رو در جدول جداگانه بريزم و نيازي به فراخواني خود تريگر ندارم راه بهتري مي شناسيد ممنون