PDA

View Full Version : مشکل در تغییر OFF کردن IDENTITY از طریق کد



AmirAmiri
جمعه 16 مهر 1389, 19:13 عصر
سلام خدمت تمامه دوستان و اساتید عزیز.
من یک جدول به نام tblPaymentsCustomers دارم که فیلد ID اون از توع bigint و IDENTITY هستش حالا بعد از پخش برنامه به دلایلی تصمیم گرفتم که توی نسخه جدید IDENTITY این فیلد رو OFF کنم و برای اینکار یک فایل آپدیت دیتابیس درست کردم که دو خطش مربوط به این کار میشه.
اون دو خط اینه :

IF IDENT_INCR('tblPaymentsCustomers') IS NOT NULL
SET IDENTITY_INSERT dbo.tblPaymentsCustomers OFF

این دو خط بدون Error اجرا میشه اما هیچ تاثیری روی جدول نمیذاره و همچنان خاصیت IDENTITY ON داره.

چکار کنم که با کد نویسی بتونم IDENTITY رو OFF کنم؟
آیا راهه دیگه ای هم داره؟
ممنون از کمک و راهنماییتون.

s.Jabbari
جمعه 16 مهر 1389, 19:37 عصر
برادر با این دستور identity فعال میشه اگه می خوای غیر فعال بشه باید ON کنی!!!

AmirAmiri
جمعه 16 مهر 1389, 19:44 عصر
برادر با این دستور identity فعال میشه اگه می خوای غیر فعال بشه باید ON کنی!!!
سلام دوست عزیز. ممنون از توجهتون اما هر چی بگی رو امتحان کردم فایده نداشته و کار نکرده. هزار بار ON و OFF کردم و اجراش کردم ولی هیچ تاثیری روی جدول نداشته. :ناراحت:

در ضمن فکر کنم اگه ON کنم IDENTITY فعال میشه پس برای غیر فعال کردن باید OFF بشه.
خواهش میکنم کمک کنید دوستان...

s.Jabbari
جمعه 16 مهر 1389, 21:02 عصر
بعد از OFF کردن با کد insert می کنی؟

AmirAmiri
جمعه 16 مهر 1389, 21:47 عصر
بعد از OFF کردن با کد insert می کنی؟
نه INSERT نمیکنم اما الان برای تست INSERT کردم و این Error رو داد:

Msg 544, Level 16, State 1, Line 1
Cannot insert explicit value for identity column in table 'tblPaymentsCustomers' when IDENTITY_INSERT is set to OFF.

دلیلش هم به خاطره اینه که فیلد ID هنوز IDENTITY هست.
وقتی کد OFF کردن رو اجرا میکنم بعد میرم توی design جدول، اونجا هنوز IDENTITY ON هست.

s.Jabbari
جمعه 16 مهر 1389, 22:45 عصر
در محیط design نمی تونی دستی insert کنی
اول دستور Identity On رو اجرا کن بعدش با دستور insert into یک سطر وارد کن.توی دستور insert مقدار فیلد identity رو خودت مشخص کن

بهزادصادقی
جمعه 16 مهر 1389, 22:54 عصر
شما چرا داری این خط را اجرا می کنی؟



IF IDENT_INCR('tblPaymentsCustomers') IS NOT NULL


به نظر می رسه که این خط همیشه جوابش false خواهد بود و در نتیجه خط دوم کد شما



SET IDENTITY_INSERT dbo.tblPaymentsCustomers OFF


هرگز اجرا نمی شود.

برای اینکه بتوانی به صورت دستی مقدار ستون identity این جدول را وارد کنی، باید خط اولت را بیاندازی و از این خط استفاده کنی:



SET IDENTITY_INSERT dbo.tblPaymentsCustomers ON


ولی حواست باشه که این باعث نمی شود که ستون دیگر identity نباشه. یعنی اگر بعد از این کد دوباره یک سطر به چدولت اضافه کنی، SQL Server دوباره مقدار ستون identity ات را خودش وارد خواهد کرد. ولی تو اجازه خواهی داشت که به صورت دستی به مقادیر این ستون دست ببری.

AmirAmiri
جمعه 16 مهر 1389, 23:56 عصر
ممنون از کمکتون دوستان.
اما من میخوام که فیلد دیگه IDENTITY نباشه.
برای این هدف باید چکار کنم؟

بهزادصادقی
شنبه 17 مهر 1389, 00:26 صبح
ممنون از کمکتون دوستان.
اما من میخوام که فیلد دیگه IDENTITY نباشه.
برای این هدف باید چکار کنم؟

تا آنجا که من می دانم، متاسفانه در SQL Server دستوری وجود نداره که بتونه خاصیت identity را از روی یک ستون برداره. برای این کار:

1. می تونی یک ستون جدید که identity نیست به جدولت اضافه کنی، بعد تمام مقادیر identity را برای تمام سطح ها از ستون idenitity خویش کپی کنی توی این ستون جدید، بعد ستون identity را از جدول حذف کنی و بعد اسم ستون جدیدت را عوض کنی به همان اسم ستون قدیمی ات.

2. یا می تونی یک جدول جدید درست کنی که ساختارش دقیقا مثل ساختار چدول حاضر است، فقط نوع ستون مورد نظرت در این جدول جدید دیگر identity نیست. بعد تمام سطرهایت را کپی کنی به جدول جدید. بعد جدول قدیمی ات را حذف کنی و بعد اسم حدول جدیدت را عوض کنی به همان اسم حدول قدیمی.

AmirAmiri
شنبه 17 مهر 1389, 00:51 صبح
ممنون آقای صادقی بازم مثل همیشه به کمکم اومدید.

تا آنجا که من می دانم، متاسفانه در SQL Server دستوری وجود نداره که بتونه خاصیت identity را از روی یک ستون برداره.
همین حرفتون خیلی کمک بزرگی چون باعث میشه بیخودی به دنبالش نباشم.
روش دومی که پیشنهاد دادید به نظرم بهتره.

حالا اگه هیچ کدومه اینکارا رو انجام ندم و خاصیت identityهم روی فیلد باشه، مشکلی که پیش نمیاد نه؟
من خودم توی یک sp برای فاکتورها و پرداخت ها شماره تولید میکنم که کده تولید پرداخت اینه :

CREATE PROC proc_GetNewPaymentID
AS
BEGIN
SELECT (ISNULL(MAX(ID),0)+1) AS ID FROM tblPaymentsCustomers
END

با این کد یک شماره پرداخت تولید میکنم و بعدش برای ثبت پرداخت جدید از همون شماره استفاده میکنم.
حالا میخوام بدونم با این کد اگه identity رو برندارم، احتمال اینکه مشکلی پیش بیاد وجود داره یا خیر؟
همین رو بگید دیگه همه مشکل م حل میشه.
باز هم خیلی ممنونم که وقت میزارید.

بهزادصادقی
شنبه 17 مهر 1389, 01:03 صبح
من نمی دونم شما به مشکل برخواهید خورد یا نه، چون با کل برنامه تون آشنایی ندارم و نمی دانم در آینده چه جوری از این جدوال استفاده خواهید کرد.

هر وقت شما یک ستون داری که identity می باشد، اگر سعی کنی به صورت دستی، چه در موقع insert کردن و یا چه در زمان update کردن یک سطر، داده ای را وارد آن ستون کنی SQL Server اعلام خطا خواهد کرد (مگر اینکه از identity_insert استفاده کرده باشی).

پس تا زمانی که شما سعی نکنی به صورت دستی مقدار این ستون را تعیین یا عوض کنی، به آن خطا بر نخواهی خورد.

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

Javad_raouf
شنبه 17 مهر 1389, 10:02 صبح
آیا انتقال identity از یک فیلد به فیلد دیگر هم امکان پذیر نیست؟

FastCode
شنبه 17 مهر 1389, 12:23 عصر
سادهترین راه:
یک نسخه از دیتابیس فعلی:
ستون مورد تظر رو IDENTITY کن.
Save
Identity رو بردار.
از toolbar گزینه Generate Change Script رو بزن.
/*
Copy
Alt+F4
Alt+F4
No
Notepad
Paste
*/
کد شما آمادست. :)

بهزادصادقی
شنبه 17 مهر 1389, 13:20 عصر
آیا انتقال identity از یک فیلد به فیلد دیگر هم امکان پذیر نیست؟

نه، امکان پذیر نیست.

AmirAmiri
شنبه 17 مهر 1389, 13:58 عصر
سادهترین راه:
یک نسخه از دیتابیس فعلی:
ستون مورد تظر رو IDENTITY کن.
Save
Identity رو بردار.
از toolbar گزینه Generate Change Script رو بزن.
/*
Copy
Alt+F4
Alt+F4
No
Notepad
Paste
*/
کد شما آمادست. :)
سلام FastCode جان.
ممنون از راهنماییت خیلی خیلی مفید بود کاش میشد به جای یک بار تشکر ، چند بار کلید تشکر رو زد. :بوس:
من اینکارو کردم و ظاهرا این کار باعث میشه یک جدول temp تولید بشه و تمامه رکوردهای جدول اصلی ریخته میشه توی جدول temp و جدول اصلی حذف میشه و بعد نام جدول temp به نام جدول اصلی تغییر میکنه.
این تقریبا همون چیزیه که جناب آقای صادقی گفتند اما با یه راه میان بر.
کدی که برای من تولید کرد این بود :

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Tmp_tblPaymentsCustomers
(
ID bigint NOT NULL,
Customer# bigint NOT NULL,
ReceivedAmount bigint NOT NULL,
Date smalldatetime NOT NULL
) ON [PRIMARY]
GO
IF EXISTS(SELECT * FROM dbo.tblPaymentsCustomers)
EXEC('INSERT INTO dbo.Tmp_tblPaymentsCustomers (ID, Customer#, ReceivedAmount, Date)
SELECT ID, Customer#, ReceivedAmount, Date FROM dbo.tblPaymentsCustomers WITH (HOLDLOCK TABLOCKX)')
GO
DROP TABLE dbo.tblPaymentsCustomers
GO
EXECUTE sp_rename N'dbo.Tmp_tblPaymentsCustomers', N'tblPaymentsCustomers', 'OBJECT'
GO
ALTER TABLE dbo.tblPaymentsCustomers ADD CONSTRAINT
PK_tblPayments PRIMARY KEY CLUSTERED
(
ID
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO
COMMIT

هم از جناب FastCode عزیز هم از جناب صادقی عزیز ممنونم.