PDA

View Full Version : خطای ارتباط با Oracle Linked Server از داخل Trigger



sknsphr
دوشنبه 04 تیر 1386, 14:35 عصر
سلام
من یه تریگر دارم:

CREATE TRIGGER trgPRT ON PRT_T FOR INSERT AS
DECLARE @CODE NUMERIC(1,0)
DECLARE @PRT NUMERIC(10,0)
DECLARE @SQL NVARCHAR(250)

SELECT @PRT=PRT_CODE FROM inserted

SET @SQL=N'SELECT @CODE=CODE1 FROM OPENQUERY(ORAINV,''SELECT MIN(CODETYPE)AS CODE1 FROM BOM.MJR_T WHERE MOJ_TYPE=2 AND MJR_DELDATE IS NULL AND PRT_PRT_CODE=' + STR(@PRT) + N''')'

EXEC SP_EXECUTESQL @SQL,N'@CODE NUMERIC(1,0) OUTPUT',@CODE

INSERT INTO tblNComponent(PRT_CODE,PrtType) VALUES(@PRT,@CODE)

GO

از تو QA به Linked Server وصل میشم و مشکلی ندارم ولی وقتی میخوام تو Table داده وارد کنم و تریگر اجرا بشه خطا میده:
The Operation could not be performed because the OLE DB provider 'MSDAORA' was unable to begin a distributed transaction.

DTC روی هر دو سرور SQL 2000 و اوراکل Run هست و حتی این تنظیمات رو رو تو Registry هر دو سرور چک کردم:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC]
"TurnOffRpcSecurity"=dword:00000001
"AllowOnlySecureRpcCalls"=dword:00000000
"FallbackToUnsecureRPCIfNecessary"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC\Securi ty]
"NetworkDtcAccess"=dword:00000001
"NetworkDtcAccessAdmin"=dword:00000001
"NetworkDtcAccessClients"=dword:00000001
"NetworkDtcAccessTransactions"=dword:00000001
"NetworkDtcAccessTip"=dword:00000001
"XaTransactions"=dword:00000001
"DomainControllerState"=dword:00000000
"AccountName"="NT AUTHORITY\\NetworkService"
"NetworkDtcAccessOutbound"=dword:00000001
"NetworkDtcAccessInbound"=dword:00000001

AminSobati
دوشنبه 04 تیر 1386, 15:04 عصر
دوست عزیزم اگر خارج از Trigger یعنی مستقیما از QA ویرایش کنین موفقیت آمیزه؟
قبلش BEGIN DISTRIBUTED TRAN انجام بدین و نتیجه رو پست کنین

AminSobati
دوشنبه 04 تیر 1386, 15:06 عصر
ضمنا SET XACT_ABORT ON هم قبلش انجام بدین

sknsphr
دوشنبه 04 تیر 1386, 15:39 عصر
ممنون از جوابتون
من فقط اطلاعات اوراکل رو میخونم بعد جدول SQL رو UPDATE میکنم.
ولی این کاری که گفتین انجام دادم باز نشد:


CREATE TRIGGER trgPRT ON PRT_T FOR INSERT AS
DECLARE @CODE NUMERIC(1,0)
DECLARE @PRT NUMERIC(10,0)
DECLARE @SQL NVARCHAR(250)

SELECT @PRT=PRT_CODE FROM inserted

SET @SQL=N'SELECT @CODE=CODE1 FROM OPENQUERY(ORAINV,''SELECT MIN(CODETYPE)AS CODE1 FROM BOM.MJR_T WHERE MOJ_TYPE=2 AND MJR_DELDATE IS NULL AND PRT_PRT_CODE=' + STR(@PRT) + N''')'

SET XACT_ABORT ON
BEGIN DISTRIBUTED TRAN

EXEC SP_EXECUTESQL @SQL,N'@CODE NUMERIC(1,0) OUTPUT',@CODE

COMMIT TRAN

INSERT INTO tblNComponent(PRT_CODE,PrtType) VALUES(@PRT,@CODE)

GO

AminSobati
دوشنبه 04 تیر 1386, 20:57 عصر
چند مطلب دانستنش شاید ما رو به جواب نزدیک کنه:
1) آیا ORAINV اسم Linked Server هست؟
2) نتیجه آزمایش مستیم در QA (بدون Trigger) رو که سوال کرده بودم پست نکردین
3) آیا از SP_EXECUTESQL حتما باید استفاده بشه؟
4) آیا در Connection مربوطه، جایی از SET IMPLICIT_TRANSACTIONS استفاده میشه؟

sknsphr
سه شنبه 05 تیر 1386, 08:12 صبح
چند مطلب دانستنش شاید ما رو به جواب نزدیک کنه:
1) آیا ORAINV اسم Linked Server هست؟
2) نتیجه آزمایش مستیم در QA (بدون Trigger) رو که سوال کرده بودم پست نکردین
3) آیا از SP_EXECUTESQL حتما باید استفاده بشه؟
4) آیا در Connection مربوطه، جایی از SET IMPLICIT_TRANSACTIONS استفاده میشه؟

1) بله
2) چرا دیگه قسمت خوندن از اوراکل مشکلی نداره.
3) آخه من باید از @PRT استفاده کنم. گویا OPENQUERY و OPENROWSET حتی CONCAT دو تا رشته رو به عنوان QUERY قبول نمیکنه
4) نمیدونم. من حتی از OPENROWSET استفاده کردم. تو QA جواب میده:

DECLARE @PRT NUMERIC(10,0)
DECLARE @SQL NVARCHAR(250)
DECLARE @CODE NUMERIC(1,0)
SELECT @PRT=29385--PRT_CODE FROM inserted

SET @SQL=N'SELECT @CODE=CASE WHEN CODE1 IS NOT NULL THEN CODE1 ELSE 1 END FROM OPENROWSET(''MSDAORA'',''***.world'';''USER'';''PA SS'',
''SELECT MIN(CODETYPE)AS CODE1 FROM BOM.MJR_T WHERE MOJ_TYPE=2 AND MJR_DELDATE IS NULL AND PRT_PRT_CODE=' + STR(@PRT) + N''')'


EXEC SP_EXECUTESQL @SQL,N'@CODE NUMERIC(1,0) OUTPUT',@CODE OUTPUT

INSERT INTO tblNComponent(PRT_CODE,PrtType) VALUES(@PRT,@CODE)

ممنون

sknsphr
سه شنبه 05 تیر 1386, 09:21 صبح
تو 2005 مشکلی نداره. SP4 رو تو 2000 نصب کردم. به خطا این خط اضافه شد:
OLE DB error trace [OLE/DB Provider 'MSDAORA' ITransactionJoin::JoinTransaction returned 0x8004d01b]

AminSobati
سه شنبه 05 تیر 1386, 10:23 صبح
همونطور که میدونین Trigger همیشه داخل یک Transaction قرار داره، پس کدی که در QA تست میکنید رو داخل Transaction قرار بدین تا ببینیم آیا مشکل از داشتن Transaction هست یا مسائل دیگه. ضمنا اگر ممکنه متن کامل خطا رو عینا پست کنین (البته اگر پیغامی که در اولین خطا ارسال کردین چیزی ازش حذف نشده دیگه لازم نیست)

sknsphr
سه شنبه 05 تیر 1386, 11:17 صبح
تو QA با Transaction همون خطا رو داد:

SET XACT_ABORT ON
BEGIN DISTRIBUTED TRAN
DECLARE @PRT NUMERIC(10,0)
DECLARE @SQL NVARCHAR(250)
DECLARE @CODE NUMERIC(1,0)
SELECT @PRT =29385--PRT_CODE FROM inserted

SET @SQL=N'SELECT @CODE=CASE WHEN CODE1 IS NOT NULL THEN CODE1 ELSE 1 END FROM OPENROWSET(''MSDAORA'',''***.world'';''user'';''pa ss'',
''SELECT MIN(CODETYPE)AS CODE1 FROM BOM.MJR_T WHERE MOJ_TYPE=2 AND MJR_DELDATE IS NULL AND PRT_PRT_CODE=' + STR(@PRT) + N''')'

EXEC SP_EXECUTESQL @SQL,N'@CODE NUMERIC(1,0) OUTPUT',@CODE OUTPUT

INSERT INTO tblNComponent(PRT_CODE,PrtType) VALUES(@PRT,@CODE)
commit tran


The operation could not be performed because the OLE DB provider 'MSDAORA' was unable to begin a distributed transaction.
OLE DB error trace [OLE/DB Provider 'MSDAORA' ITransactionJoin::JoinTransaction returned 0x8004d01b].

sknsphr
سه شنبه 05 تیر 1386, 11:19 صبح
راستی SQL من Personal Edition روی Windows XP نصبه.

AminSobati
سه شنبه 05 تیر 1386, 11:53 صبح
در QA این دستور رو اجرا کنین اول:
SET IMPLICIT_TRANSACTIONS OFF
بعد اگر واقعا نیاز نیست که دسترسی به اوراکل و عمل Insert در یک Transaction باشند، اصلا Transaction شروع نکنین و مجددا تست رو انجام بدین

sknsphr
چهارشنبه 06 تیر 1386, 08:46 صبح
اگه نخوام تو QA ، یه Transaction شروع کنم که بدون این دستور هم کار می‌کنه. ولی من اینو گذاشتم تو بدنه تریگر باز هم نشد.

CREATE TRIGGER trgPRT ON PRT_T FOR INSERT AS
SET IMPLICIT_TRANSACTIONS OFF

DECLARE @PRT NUMERIC(10,0)
DECLARE @SQL NVARCHAR(250)
DECLARE @CODE NUMERIC(1,0)
SELECT @PRT =PRT_CODE FROM inserted

SET @SQL=N'SELECT @CODE=CASE WHEN CODE1 IS NOT NULL THEN CODE1 ELSE 1 END FROM OPENROWSET(''MSDAORA'',''***.world'';''USER'';''PA SS'',
''SELECT MIN(CODETYPE)AS CODE1 FROM BOM.MJR_T WHERE MOJ_TYPE=2 AND MJR_DELDATE IS NULL AND PRT_PRT_CODE=' + STR(@PRT) + N''')'

EXEC SP_EXECUTESQL @SQL,N'@CODE NUMERIC(1,0) OUTPUT',@CODE OUTPUT

INSERT INTO tblNComponent(PRT_CODE,PrtType) VALUES(@PRT,@CODE)

GO

خطا:

Server: Msg 7399, Level 16, State 1, Line 1
OLE DB provider 'MSDAORA' reported an error. The provider did not give any information about the error.
OLE DB error trace [OLE/DB Provider 'MSDAORA' ITransactionJoin::JoinTransaction returned 0x80004005: The provider did not give any information about the error.].


فکر میکنم که SQL 2000 مشکل داره. راستی به OPTION های Provider که تو قسمت Linked Server هست ربطی نداره؟

AminSobati
پنج شنبه 07 تیر 1386, 00:30 صبح
فکر میکنم که SQL 2000 مشکل داره. راستی به OPTION های Provider که تو قسمت Linked Server هست ربطی نداره؟

بی ارتباط هم نیست. من تا به حال برای اوراکل Linked Server تنظیم نکردم. دو تا پیشنهاد دارم:
1) آخرین نسخه MDAC رو از سایت مایکروسافت دریافت و نصب کنین، شاید اشکال در درایورها باشه
2) خطایی که دریافت گردین رو در اینترنت جستجو کنین.

sknsphr
پنج شنبه 07 تیر 1386, 19:00 عصر
سلام و ممنون
راستش تو اینترنت که چند ساعتی هم گشتم. مورد مشابه هم دیدم ولی بی جواب بود. حتی یه چند تا مقاله از خود مایکروسافت هم دیدم برای Linked Server که گفته بود:
Oracle Client باید نصب باشه.
MDAC نصب باشه.
و تنظیمات رجیستری برای MSDTC هم برای ورژنهای مختلف اوراکل گفته بود چطوری باید باشه.
ولی خوب نشد. خواستم مطمئن شم که نمی شه و بعد برم سراغ 2005.
اگه راهی پیدا کردم حتما خبر می دم. :لبخندساده:

sknsphr
چهارشنبه 13 تیر 1386, 07:54 صبح
سلام
Provider رو عوض کردم و از OraOLEDB.Oracle استفاده کردم. به شرطی که تو تنظیمات Provider، گزینه Allow inprocess فعال باشه. تو فایل sqlnet.ora هم که تو همین مسیر Oracle Client و در شاخه \network\ADMIN قرار داره خط SQLNET.AUTHENTICATION_SERVICES= (NTS) رو به SQLNET.AUTHENTICATION_SERVICES= (NONE) تغییر دادم. تو 2000 هم تریگر کار می‌کنه. یعنی تریگرم اینطوری شد:

USE [QC]
GO

CREATE TRIGGER [dbo].[trgPRT] ON [dbo].[PRT_T] FOR INSERT AS

DECLARE @PRT NUMERIC(10,0)
DECLARE @SQL NVARCHAR(250)
DECLARE @CODE NUMERIC(1,0)
SELECT @PRT =PRT_CODE FROM inserted

SET @SQL=N'SELECT @CODE=CASE WHEN CODE1 IS NOT NULL THEN CODE1 ELSE 1 END FROM OPENROWSET(''OraOLEDB.Oracle'',''***.world'';''use r'';''pass'',
''SELECT MIN(CODETYPE)AS CODE1 FROM BOM.MJR_T WHERE MOJ_TYPE=2 AND MJR_DELDATE IS NULL AND PRT_PRT_CODE=' + STR(@PRT) + N''')'

EXEC SP_EXECUTESQL @SQL,N'@CODE NUMERIC(1,0) OUTPUT',@CODE OUTPUT

INSERT INTO tblNComponent(PRT_CODE,PrtType) VALUES(@PRT,@CODE)

Go