PDA

View Full Version : مبتدی: استفاده از تریگر



ozzy_mra
شنبه 10 مهر 1389, 11:55 صبح
اساتید عزیز سلام
من یه تیبل به شکل زیر دارم

CREATE TABLE [dbo].[uTblKol](
[KolSN] [dbo].[Serial] NOT NULL,
[KolTitle] [nvarchar](100) NOT NULL,
[KolCode] [nchar](10) NOT NULL,
[MahiatID] [dbo].[Serial] NOT NULL,
[VaziatID] [dbo].[Serial] NOT NULL,
[InsertDate] [nchar](10) NOT NULL,
[InsertUser] [dbo].[Serial] NOT NULL,
که serial یه تایپ از نوع decimal (18,3) هست
حالا برای اینزرت تو جدول یه sp به شکل زیر دارم

create proc [dbo].[usp_InsertKole1]
@code decimal(18,3),
@kcode varchar(6),
@ktitle nvarchar(50),
@kijaddate varchar(10),
@kusercreator decimal(18,3),
@kmahiat int,
@kvaziat int
as
INSERT INTO uTblKol (KolSN,KolCode,KolTitle,InsertDate,InsertUser,Mahi atID,VaziatID)
VALUES
(@code,@kcode,@ktitle,@kijaddate,@kusercreator,@km ahiat,@kvaziat)

چون فیلد code از نوع decimal 18,3 هست نمیشه بهش حالت identity رو نسبت داد ضمن اینکه من رو بخش اعشار کلید اصلیم یه سری اعمال مدیریتی انجام می دم
حالا برای اینزرت فیلد جدید با تریگر زیر می خوام مقدار کلید اصلی رو آپدیت کنم به این صورت که ابتدا بیشترین مقدار کلید اصلی رو انتخاب می کنم و بعد به قسمت صحیحش یه واحد اضافه می کنم و بعد یه عدد سه رقمی رو که باید به تریگر پاس بشه رو در .001 ضرب میکنم و با مقدار جدید کلید جمع می کنم و به عنوان کلید جدید درج می کنم

Create trigger utblKolTR on uTblKol
instead of insert

as
declare @kcode varchar(6),
@ktitle nvarchar(50),
@kijaddate varchar(10),
@kusercreator decimal(18,3),
@kmahiat int,
@kvaziat int,
@oscode int

declare @code decimal(18,3)
select @code = max(KolSN) from uTblKol

declare @int int
select @int = FLOOR(@code,0)
declare @ashar float
set @ashar= @code - @int
declare @newCode decimal(18,3)
set @newCode = @int + 1 + (@oscode *.001)

exec usp_InsertKole @newCode,@kcode,@ktitle,@kijaddate,@kusercreator,@ kmahiat,@kvaziat
مشکل اینجاست پارمترهایی رو که تو تریگر تعریف کردم رو چطوری مقدار دهی کنم؟
ضمناً من با سی شارپ برنامه می نویسم و اینم اولین تجربم تو استفاده از تریگرهاست
ممنون میشم راهنماییم کنید

ozzy_mra
شنبه 10 مهر 1389, 12:14 عصر
اصلاً من چطور باید پارامترهایی که به sp برای اینزرت پاس دادم رو به تریگرم بشناسونم؟؟:گریه:

Rezahak
شنبه 10 مهر 1389, 13:38 عصر
سلام
يك trigger وقتي اجرا مي شود كه يك دستور DML اجرا شود يعني شما INSERT رو انجام دهيد و بدون مقدار دهي كليد اصلي انجام INSERT با خطا مواجه مي شود و انجام پذير نيست!!!! خالا چه كار بايد كرد ؟

يك راه اين است كه همه اين كارهايي كه براي اضافه كردن مقدار كليد اصلي نوشته ايد به همراه دستور INSERT در يك transaction بنويسيد

يك راه ديگر هم اين است كه يك table داشته باشيد كه هميشه مقدار آخرين كليد اصلي را در خود نگه دارد و يك function بنويسيد كه همان كارهايي كه براي دريافت مقدار جديد كليد اصلي نوشتيد را انجام داده و در نهايت مقدار جديد را در جدول فوق UPDATE كند حالا هر زمان كه به مقدار جديدي براي كليد اصلي نياز داشتيد آن تابع را صدا بزنيد

M.YasPro
شنبه 10 مهر 1389, 13:43 عصر
سلام
بعد از اینسرت در یک جدول می تونی با کلمه کلیدی inserted به رکوردی که باعث اجرای تریگر(یعنی رکورد اینزرت شده) دسترسی داشته باشی .
مثلا


declare @name nvarchar(10)
select @name=@name from inserted

شما با کارهایی که بالا کردی می خوای به چه هدفی برسی ، اگر اونو بگی خیلی بهتر میشه کمکت کرد .
موفق باشید .

Rezahak
شنبه 10 مهر 1389, 13:49 عصر
M.Yaspro:
شما فرموديد بعد از INSERT كردن .... در صورتي كه ايشون به دليل اينكه نمي توانند مقداري براي كليد اصلي اختصاص دهند اصلا قادر به انجام عمل INSERT نمي باشند

M.YasPro
شنبه 10 مهر 1389, 14:01 عصر
من منطق شما برای "اعمال مدیریتی روی فیلد کلید" رو نمیدونم ولی میشه به جای اینکار از ترکیب دو فیلد عددی صحیح به جای یک فیلد اعشاری برای PK استفاده کرد .

ozzy_mra
شنبه 10 مهر 1389, 14:07 عصر
سلام
بعد از اینسرت در یک جدول می تونی با کلمه کلیدی inserted به رکوردی که باعث اجرای تریگر(یعنی رکورد اینزرت شده) دسترسی داشته باشی .
مثلا


declare @name nvarchar(10)
select @name=@name from inserted

شما با کارهایی که بالا کردی می خوای به چه هدفی برسی ، اگر اونو بگی خیلی بهتر میشه کمکت کرد .
موفق باشید .

سلام و ممنون از راهنماییتون
من دارم یه برنامه می نویسم که مثلاً از چند شعبه به دیتا بیس متصل می شوند برای هر شعبه یه کد منحصر بفرد دارم ، قصد من اینه که اولاً با درج هر ردیف از اطلاعات مشخص بشه که چه شعبه ای این اطلاعات رو درج کرده که به کمک بخش اعشاری کلید اصلیم این کار رو می خوام انجام بدم و اینکه چون یه سیستم حسابداری هست باید اطلاعات هر شعبه رو فقط به خودش نشون بدم که باز هم از این رقم اعشاری برای این کار استفاده می کنم
مثلاً کد 12.102 ینعی رکورد 12 از شعبه 102 و بعد ممکنه که 12.103 رو هم داشته باشم که میشه رکورد 12 از اطلاعات شعبه 103
حالا یه سوال دیگه وقتی از تریگر insted of استفاده می کنم یعنی اینکه به جای دستور اینزرت اولیه دستورات تریگر من رو انجام بده و در واقه چیزی اینزرت نشده اونوقت استفاده از inserted مقدار null بر نمی گردونه؟

M.YasPro
شنبه 10 مهر 1389, 14:35 عصر
درسته null بر میگردونه .
با توجه به توضیحات بالای شما ، بازم دلیلی نمیبینم که از کلید اعشاری استفاده کنید .
می تونید دو تا فیلد داشته باشید .
از ساختار دیتابیستون یه تصویر بزارید اصلاحش کنیم .

ozzy_mra
شنبه 10 مهر 1389, 15:00 عصر
درسته null بر میگردونه .
با توجه به توضیحات بالای شما ، بازم دلیلی نمیبینم که از کلید اعشاری استفاده کنید .
می تونید دو تا فیلد داشته باشید .
از ساختار دیتابیستون یه تصویر بزارید اصلاحش کنیم .

خب کلاً واسه این کار از چه روشی باید استفاده کرد؟
هرچند استفاده از دو فیلد راحت تره ولی باعث ایجاد افزونگی داده نسبت به حالت من نمیشه؟؟
دلیل اصلی استفاده از این ساختار تو برنامم اینه که این برنامه باید با حداقل سه دیتا بیس از برنامه های سازمانهای دیگه در ارتباط باشه که تو همگی اونا از این استاندارد اعشاری استفاده کردند که اگه من بخوام تغییری ایجاد کنم خیلی به مشکل بر میخورم

M.YasPro
شنبه 10 مهر 1389, 16:57 عصر
چرا این کارهایی که میگید رو توی استر انجام نمی دید و اون اعمال مدیریتی رو انجام بدید و اگر خواستید اینزرت کنید؟

M.YasPro
شنبه 10 مهر 1389, 17:13 عصر
حالا یه سوال دیگه وقتی از تریگر insted of استفاده می کنم یعنی اینکه به جای دستور اینزرت اولیه دستورات تریگر من رو انجام بده و در واقه چیزی اینزرت نشده اونوقت استفاده از inserted مقدار null بر نمی گردونه؟

تست کردم null نیست
کدتون باید یه همچین چیزی باشه :


create triger tr
on table
instead of insert
as
begin
declare @id int
declare @name nvarchar(50)
select @id=id from inserted
select @name=name from inserted
.
.
اعمال مدیریتی
.
.
insert into table values(@id,@name,....)
end

ozzy_mra
یک شنبه 11 مهر 1389, 08:35 صبح
چرا این کارهایی که میگید رو توی استر انجام نمی دید و اون اعمال مدیریتی رو انجام بدید و اگر خواستید اینزرت کنید؟
به ناچار همین کار رو هم انجام دادم و توسط یه function این عمل رو انجام دادم ولی استفاده از تریگر سرعت کار رو بیشتر میکنه مخصوصاً زمانی که تعداد رکورد ها به چند میلیون میرسه
من از این تابع استفاده کردم :

Create function [dbo].[fn_UpdateKole] (@oscode decimal(18,3))
returns decimal(18,3)
as
begin

declare @old decimal(18,3)
select @old=max(KolSN) from uTblKol where (KolSN - FLOOR(KolSN) = @oscode)
declare @int decimal(18,3)
select @int = FLOOR(@old)
declare @newCode decimal(18,3)
set @newCode = (@int + 1) + @oscode

return @newCode
end

ozzy_mra
یک شنبه 11 مهر 1389, 09:23 صبح
تست کردم null نیست
کدتون باید یه همچین چیزی باشه :


create triger tr
on table
instead of insert
as
begin
declare @id int
declare @name nvarchar(50)
select @id=id from inserted
select @name=name from inserted
.
.
اعمال مدیریتی
.
.
insert into table values(@id,@name,....)
end


ممنون این درسته ولی من چطور می تونم یه پارامتر به غیر از اونی که اینزرت کردم رو به تریگرم پاس بدم؟مثلاً یه عدد خاصی رو پاس بدم که با یه فیلدم جمع بزنه؟

M.YasPro
یک شنبه 11 مهر 1389, 13:54 عصر
من اطلاعی ندارم که سرعت تریگر بیشتره یا استور
ولی شما نمی تونی به تریگر پارامتر پاس بدی(تا اونجایی که من می دونم ) یعنی شما اصلا متغیری پاس نمیدی بلکه به اون مقادیری که اخیرا اینزرت شدن دسترسی داری .
اگه بتونی توی پارامترهایی که برای اینزرت میفرستی مقدار دلخواهتو با یکیشون بفرستی و توی تریگرت اون مقدار رو تجزیه کنی فکر کنم کارتون راه میوفته.
مثلا اگر فیلد KolTitle رو قبل از ارسال یه عدد بهش ضمیمه کنی :


KolTitle= KolTitle+#number

و توی تریگر مورد نظر عدد رو از پارامتر KolTitle استخراج کنی .


موفق باشید .