View Full Version : خطا در کمپایل پروسیجر در صورتی که دو بار دستور into داشته باشد
daneshmand1354
جمعه 31 شهریور 1391, 17:11 عصر
ضمن سلام چرا پروسه زیر در زمان کمپایل خطا میدهد
create PROCEDURE p1
as
declare @i as int
set @i=1
if (@i=1) begin
select * into #t1 from bank
end else begin
select * into #t1 from bank2
end
efarzad
چهارشنبه 12 مهر 1391, 10:09 صبح
متن خطا چی هست ؟
حمیدرضاصادقیان
چهارشنبه 12 مهر 1391, 10:17 صبح
سلام.
چند تا ایراد دستور شما داره. اولین ایراد تعریف متغیر شماست. این به کاری نمیاد.چون شما متغیر رو داخل خود SP تعریف کرده و بهش یک مقدار ثابت ارسال کردید و درنهایت دستور IF شما اجرا نمیشه.
دومین مورد این هست که با استفاده از Select Into جدول ایجاد میشه. وقتی یک بار جدول ایجادمیشه برای مرتبه دوم نمیتونه باهمون نام ایجاد بشه به همین خاطر بهتون خطا میده.
من دستورات شما رو به شکل زیر تغییر دادم.
create PROCEDURE p1 @I INT
as
if (@i=1)
select * into #t1 from bank
else
select * into #t2 from bank2
GO
behnam_one
چهارشنبه 12 مهر 1391, 11:29 صبح
منطق پروسيجر نوشته شده درسته
اشكال پروسيجر شما فقط به خاطر در نظر گرفتن دو جدول مجازي همنام هستش
حمیدرضاصادقیان
چهارشنبه 12 مهر 1391, 13:42 عصر
منطق پروسيجر نوشته شده درسته
رو چه اصولی این حرفو میزنید؟ متغیری که تعریف شده عملا کاری نمیکنه و اون IF هیچ کاربردی اونجا نداره.!!
behnam_one
یک شنبه 16 مهر 1391, 20:06 عصر
البته از نظر من منطق برنامه درسته! چرا؟
بخاطر اینکه این سطور از برنامه مشکل ایجاد نمیکنه و درسته که کاری انجام نمیده حرف شما متین
ولی من به درخواست دوستمون توجه کردم که گفته بودن : خطای برنامه من کجاست ؟نگفته بودن که این PROCEDURE من رو بهینه کنین
daneshmand1354
سه شنبه 18 مهر 1391, 08:41 صبح
با تشکر از دوستانی که در بحث شرکت کردند
دستوری که من نوشته ام دو دستور into در آن است که با توجه به شرط گذاشته شده فقط یکی از این دو دستور اجرا میشود مثلا فرض کنیم که اطلاعات فاکتور فروش در bank1 و فاکتور خرید در bank2 ذخیره شده است .
با استفاده از دستور set @i=1 و یا set @i=2 به پروسیجر فرمان می دهیم که اکنون کدام بخش if اجرا می شود در صورتی که هر یک از متغیرها مقدار داده شود یکی از دو جدول به #t1 ریخته میشود
بنابراین هیچگاه دو دستور با هم اجرا نمی شوند که بگوییم خطای وجود جدول قبلی را میدهد
این دستور در زمان کمپایل خطا می دهد
خطا این است
There is already an object named '#t1' in the database.
کمپایلر اسکیوال تشخیص نمی دهد که دو دستور در یک شرط if قرار دارند و در هر زمان فقط یک دستور اجرا میشود
Nima_kyan
سه شنبه 18 مهر 1391, 09:52 صبح
خطا این است
There is already an object named '#t1' in the database.
کمپایلر اسکیوال تشخیص نمی دهد که دو دستور در یک شرط if قرار دارند و در هر زمان فقط یک دستور اجرا میشود
این خطا نشون میده که جدول t1 تو بانکت وجود داره.
دستور شما سعی میکنه جدولی به نام t1 بسازه در صورتی که این جدول قبلا ساخته شده.
آقای صادقیان هم بالا توضیح دادن.
با استفاده از Select Into جدول ایجاد میشه. وقتی یک بار جدول ایجادمیشه برای مرتبه دوم نمیتونه باهمون نام ایجاد بشه به همین خاطر بهتون خطا میده.
شما به صورت دستی جدول t1 رو حذف کنید بعد پردازتون رو اجرا کنید. پردازه اجرا میشه ولی فقط بار اولی که اجراش کنید بدون خطا خواهد بود.
behnam_one
چهارشنبه 19 مهر 1391, 10:22 صبح
دوست عزيز
همان طور كه خودتون هم نوشتيد SQL متوجه نميشه كه اين جداول داخل IF قرار گرفتن،بنابراين Error برميگردونه
براي حل مشكل اولا بايد دو جدول مجازي غير همنام انتخاب كنيد با اين كار خطاي زمان كامپايل شما رفع ميشه ولي موقع اجرا دوباره خطا ميده ، علت خطا هم اينه كه با كانكشني كه از سمت برنامه اين پروسيجر رو صدا ميزنيد يك بار جداول ساخته ميشه و براي بار دوم اجازه ساخت مجدد رو نميده بنابر اين اگر شما پروسيجرتون رو به اين شكلي كه من در زير نوشتم بنويسين هيچ مشكلي در اجرا و يا كامپايل مشاهده نخواهين كرد -- اميدوارم مطالب گويا باشد
پروسيجر مورد نظر شما بايد به اين شكل نوشته شده باشه تا خواسته شما رو براورده كنه
CREATE PROCEDURE p1
(
@I as TinyInt
)
as
BEGIN
declare @ExistTemp_1 int
Select @ExistTemp_1 =Object_Id('Tempdb.dbo.#t1')
IF IsNull(@ExistTemp_1,0)<>0 drop table #t1
declare @ExistTemp_2 int
Select @ExistTemp_2 = Object_Id('Tempdb.dbo.#t2')
IF IsNull(@ExistTemp_2,0)<>0 drop table #t2
if (@i=1) begin
select * into #t1 from bank
end else begin
select * into #t2 from bank2
end
END
daneshmand1354
جمعه 05 آبان 1391, 10:59 صبح
اجازه بدهید سوالم را ساده تر طرح کنم
چرا پروسه زیر خطا میدهد در صورتی که هیچ مشکل منطقی ندارد
create procedure p1 as
select * into #t1 from bank1
drop table #t1
select * into #t1 from bank1
متن خطا
There is already an object named '#t1' in the database.
به نظر من این یک باگ بسیار بزرگ در اسکیوال است
خوب است به میکروسافت اطلاع بدهیم
دوستان دقت کنند به همین سوال پاسخ دهند و صورت مسئله را عوض نکنند
مثلا مانند بالا ننویسید که نام جدول دوم را #t2 بگذار
behnam_one
جمعه 05 آبان 1391, 15:59 عصر
من فکر میکردم شما به دنبال رفع مشکل پروسیجری که نوشتین هستین و ادامه کار، نه رفع باگ SQL و گزارش ان به ماکروسافت
در هر حال موفق باشید
حمیدرضاصادقیان
جمعه 05 آبان 1391, 22:25 عصر
دوست عزیز شما قبل از اینکه بخواهید از Microsoft ایراد بگیرید و Bug رو Report کنید!! سعی کنید با منطق کار آشنا بشین بعد اگر در اون منطق خطایی مشاهده کردید اونو Report کنید.
این هیچ مشکلی نداره.به خاطر اینکه یک کار بیهوده و بی منطق داره رخ میده. اگر همین دستورات رو به صورت جدا از هم و با استفاده از Go از همدیگه جداکنید کل اونها اجرا خواهندشد.
وقتی یک شی یک بار ایجاد میشه دیگه نیازی به ایجاد دوباره اون نیست و میتوان با خالی کردن محتویات آن کار را ادامه داد.
پیشنهاد میکنم فصل اول کتاب Inside SQL querying 2008 مربوط به Itzik Ben gan رو مطالعه کنید تا متوجه بشین چرا این داره خطا میده.!!
موفق باشید.
daneshmand1354
دوشنبه 08 آبان 1391, 23:03 عصر
دوستان گرامی
گویا من با اینکه بارها سوالم را مطرح کرده ام باز باید سوالم را مطرح کنم
من یک پروسیجر می خواهم بنویسم که در آن دو بار دستور select into #t1 تکرار میشود
اگر همین دستورات رو به صورت جدا از هم و با استفاده از Go از همدیگه جداکنید کل اونها اجرا خواهندشد.
در یک پروسیجر نمی توان go گذاشت زیرا آنرا به معنی پایان پروسیجر دستور تشخیص می دهد
من فکر میکردم شما به دنبال رفع مشکل پروسیجری که نوشتین هستین و ادامه کار، نه رفع باگ SQL و گزارش ان به ماکروسافت
شما به جای اینکه جواب سوال مرا بدهید به جزئیات پرداخته اید
من نمی خواهم چیزی به میکروسافت گزارش کنم.اگر می خواستم به میکروسافت بنویسم که اینجا نمی نوشتم.
باز سوالم را تکرار می کنم
من می خواهم یک پروسیجر بنویسم که دو دستور select * into #t1 دارد
فرض کنید بین این دو دستور صد دستور دیگر هم قرار دارد
من برای سادگی مطلب سه دستور را پشت سر هم نوشتم
حمیدرضاصادقیان
سه شنبه 09 آبان 1391, 09:06 صبح
در یک پروسیجر نمی توان go گذاشت
بله اینو میدونم. منظورم در یک Transaction در داخل یک Query معمولی بود نه SP.
دوست عزیز نمیدونم چرا اینقدر اصرار دارید یک کار اشتباه رو انجام بدین؟؟
Parser کنترل میکنه در داخل SP شما که یک شی یک بار ایجاد بشه.
این یک راه برای انجام این مورد شما هست.
alter PROCEDURE uspTest
AS
DECLARE @Str NVARCHAR(1000)
SET @Str=N'SELECT * INTO #T1 FROM table1';
Execute sp_executesql @Str
IF OBJECT_ID('#t1') IS NOT NULL
DROP TABLE #T1
SELECT * Into #T1 FROM Table1
GO
ولی قبل از همه اینها کتابی که پیشنهاد دادم رو حتما مطالعه کنید تااز منطق کد نویسی کاملا مطلع شوید.
daneshmand1354
یک شنبه 14 آبان 1391, 18:01 عصر
alter PROCEDURE uspTest
AS
DECLARE @Str NVARCHAR(1000)
SET @Str=N'SELECT * INTO #T1 FROM table1';
Execute sp_executesql @Str
IF OBJECT_ID('#t1') IS NOT NULL
DROP TABLE #T1
SELECT * Into #T1 FROM Table1
GO
با سلام
دوست گرامی
با تشکر از شما
این پاسخ شما مشکل را رفع می کند ولی باز هم جواب سوال من نیست
گذاشتن دستور در یک رشته مشکل را رفع می کند ولی اسکیوال این گونه دستورات را خطایابی نمی کند .
هدف من فقط رفع مشکل نیست من می خواهم کدی بنویسم که اسکیوال آنرا کمپایل کند.
اگر دستوری که من نوشته ام به هیچ عنوان نمی تواند درست باشد و باید از دستورات مشابهی مانند دستور شما استفاده شود پس می رسیم به حرف اول من
یعنی اسکیوال سرور در اینجا مشکل دارد.
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.