PDA

View Full Version : راهنمایی در مورد یک تریگر لطفا



mojtaba.baghban
پنج شنبه 26 شهریور 1388, 22:44 عصر
اگر بخواهیم یکتایی ستونی را با استفاده از تریگر بررسی کنیم(میدانم که با استفاده از قیود یونیک قابل اجراست، صرفا یک مثال است برای بررسی مشکل ) اکر تریگر را بصورت زیر بنوسیم


create table test
(
number int
)



create trigger tg_test_insert
on test
for insert
as
begin
if exists
(
select 'true'
from test as t
join inserted as i
on t.number=i.number
)
rollback tran
end

هیچوقت نمی توانیم داده ای را در جدول قرار دهیم زیرا تریگر همیشه بعد از درج در جدول اجرا میشود و if درون تریگر همیشه اجرا خواهد شد و تراکنش را لغو می کند

AminSobati
پنج شنبه 26 شهریور 1388, 23:55 عصر
شما ظاهرا قصد دارین از درج مقدار تکراری جلوگیری کنید که طبیعتا این Trigger باید این کار رو انجام بده. اما اگر در Trigger میخواین مقدار دیگری جایگزین مقدار کاربر کنین، از Trigger در حالت Instead of استفاده کنید

mojtaba.baghban
جمعه 27 شهریور 1388, 00:08 صبح
شما ظاهرا قصد دارین از درج مقدار تکراری جلوگیری کنید که طبیعتا این Trigger باید این کار رو انجام بده
اما در واقع می بینیم که این تریگر کار رو به غلط انجام میده وبجای جلوگیری از درج مقادیر تکراری از درج هر مقداری جلوگیری می کند

AminSobati
جمعه 27 شهریور 1388, 00:20 صبح
یا از instead of استفاده کنید یا count بگیرید

mojtaba.baghban
جمعه 27 شهریور 1388, 00:34 صبح
از چی count بگیرم؟

محمد سلیم آبادی
جمعه 27 شهریور 1388, 06:08 صبح
می خواهید مانع از درج مقادیر تکراری در یک جدول با کمک trigger شوید؟
البته جدا از Unique Constraint و Instead of Insert trigger یک روش دیگر وجود دارد که از trigger بهتر است در واقع برای تکمیل trigger شما نیاز به پردازش row-by-row دارید ولی این روشی که من می گویم به این موضوع احتیاجی ندارد. این روش CHECK() Constraint based on UDF است.



create table t1
(
i int
)
go

create trigger trg
on t1
instead of insert
as
begin
if exists(
select * from inserted where i in (select i from t1))
rollback tran
else insert t1 select * from inserted
end
--=======================
--======== OR =========
--=======================
go
create trigger trg1
on t1
instead of insert
as
begin
if not exists(
select * from inserted where i in (select i from t1))
insert t1 select * from inserted
else raiserror('Hey Be Carful!',1,1)
end
--Why Wait! Try it hurry up!
insert t1 values(1)
insert t1 values(2)
insert t1 values(1)

محمد سلیم آبادی
جمعه 27 شهریور 1388, 07:00 صبح
اوه، Uniqe Constraint مانع از درج null تکراری می شود! این مورد را در trigger ای که برای شما پست کردم در نظر نگرفتم. در واقع NULL یکمی چموش است یعنی با عملگر های = و in ترتیب اثر نمی دهد.

به مثال زیر توجه کنید:


select 1
where null in (select null)

select 1
where null in (null)

select 1
where null=null


خب، ولی یکمی روی query مربوطه ی trigger کار کردم و این موضوع را نیز روی آن اعمال کردم که به شکل نهایی زیر در آمد.
البته شاید لغمه را دور سرم چرخونده باشم، نمی دانم، چون از دیشب تا حالا نخوابیدم و الان هم ساعت نزدیک هفت و نیم است.




create trigger trg1
on t1
instead of insert
as
begin
if not exists(
select * from inserted where i in (select i from t1)
or 1=case when i is null then
case when exists (select * from t1 where i is null) then 1
end end)
insert t1 select * from inserted
else raiserror('Hey Be Carful!',1,1)
end
--Why Wait! Try it hurry up!
insert t1 values(null)
insert t1 values(null)
insert t1 values(1)

mojtaba.baghban
جمعه 27 شهریور 1388, 14:01 عصر
با تشکر از راهنمایی آقای msalim و sobati خدمت آقای msalim عرض کنم که تریگر ی که نوشته اید در صورتیکه در خود جدول inserted مقادیر تکراری وجود داشته باشد این مقادیر تکراری را وارد جدول می کند

محمد سلیم آبادی
جمعه 27 شهریور 1388, 14:49 عصر
همانطوری که در پست شماره ی 6 گفتم برای تکمیل هر trigger ای ما نیاز به پردازش row-by-row داریم که این مهم توسط cursor یا loop یا هرچیزی که ماهیت بازگشتی داشته باشد امکان پذیر است.
مثلا فرض کنید با یک دستور insert سعی می کنیم ده سطر با مقادیر یکسان را درج کنیم یک trigger ساده نمیاید که سطر به سطر را درج کند وسطر بعدی را چک کند همینطور تا آخر. خب در نتیجه تا مقداری که درج نشده است پس مقدار تکراری نیز نخواهد بود.
فعلا برای ماست مالی کردم قضیه قبل از درج سطرهای جدول مجازی در جدول اصلی از کلید واژه DISTINCT استفاده کنید تا بلکه یک مقاله خوبی در این موضوع یعنی "Check Existing Data befor inserting by a TRIGGE" بنویسم.

برای استفاده از Cursor
http://www.barnamenevis.org/forum/showthread.php?t=176785

محمد سلیم آبادی
جمعه 27 شهریور 1388, 14:56 عصر
البته باید عرض کنم تنها برای مقاصد آموزشی از این روش استفاده کنید. همانطوری که تا حالا دیده اید برای تکمیل یک trigger ای که واقعا صد در صد کار یک Unique Constraint یا Unique Key را انجام دهد باید زحمت فراوانی متحمل شویم از جمله:
مساله Fail
مساله درج مقادیر تکراری NULL
مساله پردازش Row-By-Row
مساله بررسی هنگام درج و هم هنگام ویرایش
و ...

وای اینقدر بررسی! خب چرا از Unique Key استفاده نکنیم؟

mojtaba.baghban
جمعه 27 شهریور 1388, 16:46 عصر
قصد من یاد گرفتن روش برای استفاده در تریگرهای دیگر است در واقع هر تریگری از نوع اینزرت که برسی را روی خود
جدولی که در آن اینزرت انجام می دهد اعمال می کند با این مشکل روبرو است