PDA

View Full Version : راه غیر از تریگر



Mahdad999
دوشنبه 22 اسفند 1390, 20:12 عصر
سلام دوستان،
یه تیبل دارم که با xml چند سطر توش insert میشه به ازائ هر insert توی این جدول نیاز دارم توی جدول دوم سطر متناظر جدول اول رو update کنم. از تریگر نمیتونم استفاده کنم چون توی هر بار صدا کردن یه بار عمل میکنه
به نظر شما باید از چه روشی برای update جدول دوم استفاده کنم؟

mahan.2002
سه شنبه 23 اسفند 1390, 01:06 صبح
سلام
شما زمانی که عمل اینسرت رو انجام دادی در ادامه کد خودتون عمل Update رو انجام بدید.

Mahdad999
سه شنبه 23 اسفند 1390, 07:00 صبح
ببینید بذارید یه جور دیگه هم توضیح بدم!
جدول اول من جدول فاکتوره
دومی لیست کالا هاست
من چند تا کالا رو باید با یک query به جدول فاکتور اضافه کنم برای اینکار از xml استفاده کردم
حالا به ازائ هر کالایی که به فاکتو اضافه شده باید:
1- تعداد کالای تو فاکتور از مقدار موجودی فعلی جدول کالا کم بشه
2- تعداد کالای تو فاکتور از مقدار موجودی کلی جدول کالا کم بشه
یعنی عملا یه همچین update ای باید باشه:

update dbo.Goods
set
WholeGoodNum = CONVERT(int,WholeGoodNum)- (select GPQuantity from openXml(@xmlHandle, '/NewDataSet/SelectedGoods',1) WITH (GPQuantity int '@GPQuantity')),
GoodAvailablity = CONVERT(int,GoodAvailablity) - (select GPQuantity from openXml(@xmlHandle, '/NewDataSet/SelectedGoods',1) WITH (GPQuantity int '@GPQuantity'))
where GoodsId in (select GoodsId from openXml(@xmlHandle, '/NewDataSet/SelectedGoods',1) wITH (GoodsId int '@GoodsId'))


دلیل اونم اینه که برای هر id کالا تعداد انتخابی فرق میکنه و از طرفی تعداد کالامون هم میتونه از 1 تا ... متغیر باشه
برای ایین مدل update کردن به من error میده (خوب حقم داره) میگه تعداد متغیر ها زیاده!
حالا فکر کنم سوال من واضح تر شده باشه
ممنون میشم اگه راهنماییم کنید

baktash.n81@gmail.com
سه شنبه 23 اسفند 1390, 09:05 صبح
وقتی می خوای چنتا کالا رو مقادیرشو Update کنی ... احتمالا نیاز به حلقه داری ... یکی یکی کالا ها رو از تو فاکتو بخونی بعد به ازای هر کدوم یه Update بزنی ...

یا اینکه لیست کالا های موجود تو فاکتور رو بریزی توی TempTable بعد این Temp رو با جدول کالا Join کنی و Update کنی ...

Mahdad999
سه شنبه 23 اسفند 1390, 15:59 عصر
وقتی می خوای چنتا کالا رو مقادیرشو Update کنی ... احتمالا نیاز به حلقه داری ... یکی یکی کالا ها رو از تو فاکتو بخونی بعد به ازای هر کدوم یه Update بزنی ...

یا اینکه لیست کالا های موجود تو فاکتور رو بریزی توی TempTable بعد این Temp رو با جدول کالا Join کنی و Update کنی ...
سلام
میشه راجع به روش اول (حلقه) بیشتر توضییح بدید؟
توی sql حلقل رو چطور میشه پیاده کرد؟
اگه میشه یه نمونه کد کوچیک راجع به پیشنهادهایی که دادید برام بذارید

baktash.n81@gmail.com
چهارشنبه 24 اسفند 1390, 08:34 صبح
حلقه با استفاده از دستور While ساخته می شه ... به این صورت
WHILE Boolean_expression { sql_statement | statement_block | BREAK | CONTINUE }

برای روش دوم ... یک تابع از تعریف می کنیم که شماره سند فاکتور رو می گیره و جدول اقلام داخل فاکتور رو به صورت جدول بر می گردونه ... (table Value Function) بعد این جدول رو می تونی به عنوان یه جدول واقعی استفاده کنی یعنی ازش Select بگیری یا یه جدول دیگه رو باهاش Join کنی ... این جدول رو تو دستور Update با جدول مقدار Join می کنی و تعداد فروخته شده رو از تعداد موجود کم می کنی ...

USE AdventureWorks2008R2;
GO
IF OBJECT_ID (N'Sales.ufn_SalesByStore', N'IF') IS NOT NULL
DROP FUNCTION Sales.ufn_SalesByStore;
GO
CREATE FUNCTION Sales.ufn_SalesByStore (@storeid int)
RETURNS TABLE
AS
RETURN
(
SELECT P.ProductID, P.Name, SUM(SD.LineTotal) AS 'Total'
FROM Production.Product AS P
JOIN Sales.SalesOrderDetail AS SD ON SD.ProductID = P.ProductID
JOIN Sales.SalesOrderHeader AS SH ON SH.SalesOrderID = SD.SalesOrderID
JOIN Sales.Customer AS C ON SH.CustomerID = C.CustomerID
WHERE C.StoreID = @storeid
GROUP BY P.ProductID, P.Name
);

SReza1
شنبه 27 اسفند 1390, 17:18 عصر
دوست عزيز ميتوني از همون trigger استفاده كني . دقت كن به ازاي هر transaction تريگر يكبار ايجاد ميشه . ولي ميتوني در يك حلفه از جدول سيستمي INSERTED اطلاعات را fetch كني.
فكر كنم با يك cursor خيلي راحت ميتوتي اطلاعات را پردازش كني و هر كاري خواستي بكني
يك cursor روي جدول سيستمي inserted بنويس.

Mahdad999
پنج شنبه 03 فروردین 1391, 01:41 صبح
حلقه با استفاده از دستو
برای روش دوم ... یک تابع از تعریف می کنیم که شماره سند فاکتور رو می گیره و جدول اقلام داخل فاکتور رو به صورت جدول بر می گردونه ... (table Value Function) بعد این جدول رو می تونی به عنوان یه جدول واقعی استفاده کنی یعنی ازش Select بگیری یا یه جدول دیگه رو باهاش Join کنی ... این جدول رو تو دستور Update با جدول مقدار Join می کنی و تعداد فروخته شده رو از تعداد موجود کم می کنی ...

من روش شما رو به این صورت اجرا کردم ولی به عنوان یک تیبل نتونستم ازش استفاده کنم آیا کار من ایرادی داشته؟

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
CREATE FUNCTION ListedGoodsInGP(@GPNumber int)
RETURNS TABLE
AS
RETURN
(
SELECT G.GoodsId, G.GoodsName, G.GoodAvailablity ,G.WholeGoodNum, GPD.GPQuantity
FROM dbo.Goods AS G
JOIN dbo.GatePassDetail AS GPD ON GPD.goodsId = G.goodsId
JOIN dbo.GatePassMaster AS GPM ON GPM.GPId = GPD.GPId
WHERE GPM.GPNum = 123
GROUP BY G.GoodsId, G.GoodsName, G.GoodAvailablity ,G.WholeGoodNum, GPD.GPQuantity
---
)
GO

Mahdad999
پنج شنبه 03 فروردین 1391, 01:45 صبح
دوست عزيز ميتوني از همون trigger استفاده كني . دقت كن به ازاي هر transaction تريگر يكبار ايجاد ميشه . ولي ميتوني در يك حلفه از جدول سيستمي INSERTED اطلاعات را fetch كني.
فكر كنم با يك cursor خيلي راحت ميتوتي اطلاعات را پردازش كني و هر كاري خواستي بكني
يك cursor روي جدول سيستمي inserted بنويس.

سلام،
من از تریگر استفاده کردم ولی با توجه به اینکه تریگر فقط برای یک عمل insert یا Update یک بار فعال میشه ولی در یک update من چند سطر باید تغییر کنن بعد از insert کردن فقط یک سطر کالا update میشه!

Mahdad999
پنج شنبه 03 فروردین 1391, 01:56 صبح
استفاده كني . ولي ميتوني در يك حلفه از جدول سيستمي INSERTED اطلاعات را fetch كني.


من این کد رو برای inserted نوشتم توی تریگر ولی همانطور که گغتم فقط اولین سطر کالا update میشه:
Alter trigger Trg_update_GoodsAfterInsertGP
on dbo.Test
for Insert
As
declare @iden int
set @iden =(select GoodsId from Inserted)-- @@identity
declare @GoodNum int
set @GoodNum = (Select GPQuantity from Inserted) --Test where GoodsId = @iden)

update dbo.Goods
set
Goods.WholeGoodNum = convert(int,Goods.WholeGoodNum) - @GoodNum,
Goods.GoodAvailablity = convert(int,Goods.GoodAvailablity) - @GoodNum
where Goods.GoodsId= @iden
raiserror('%d Triger anjam shod',0,1,@@rowcount)

nedata
پنج شنبه 03 فروردین 1391, 12:53 عصر
نياز به حلقه نيست

Alter trigger Trg_update_GoodsAfterInsertGP
on dbo.Test
for Insert
As

update dbo.Goods
set
WholeGoodNum = convert(int,g.WholeGoodNum) - i.GPQuantity,
GoodAvailablity = convert(int,g.GoodAvailablity) - i.GPQuantity
from goods g join inserted i on
g.goodsid=i.goodsid
raiserror('%d Triger anjam shod',0,1,@@rowcount)

baktash.n81@gmail.com
شنبه 05 فروردین 1391, 09:23 صبح
یه نگاهی به تابعی که نوشتی انداختم ... مشکلی نداره ... کجا به مشکل برخوردی ؟!

Mahdad999
یک شنبه 27 فروردین 1391, 20:58 عصر
یه نگاهی به تابعی که نوشتی انداختم ... مشکلی نداره ... کجا به مشکل برخوردی ؟!

ممنون طبق کد کاربر محترم nedata عمل کردم حل شد

ASKaffash
دوشنبه 28 فروردین 1391, 09:37 صبح
سلام
حق با کاربر SReza1 است از ترکییب Insert Into MyLog Select A,B,C,... From Inserted می توانید در یک تراکنش کار را انجام دهید