PDA

View Full Version : چگونه کد و داده های خود را پست کنیم تا بهترین جواب را بگیریم



محمد سلیم آبادی
جمعه 06 شهریور 1388, 21:28 عصر
چگونه کد و داده های خود را پست کنیم تا بهترین جواب را بگیریم
قبل از هر چیزی لازم است که به این نکته اشاره شود: روزی یک کتاب مربوط به SQL Server 2000 را می خواندم نویسنده آن کتاب نوشته بود "دستورات DML که شامل دستورات SELECT, INSERT, UPDATE, DELETE می شوند در تمام نسخه های مختلف SQL Server یکسان خواهند بود ولی دستورات DDL در نسخه های مختلف تغییر می کنند" ولی اینطور نشد. با release شدن نسخه SQL Server 2005 ماده ها (clause) و عملگرها (Operator) زیادی به SELECT Statement اضافه شد این باعث شد که بتوانیم از راههای ساده تری به result های مشابه ای برسیم، خواسته ی من از شما این است که حتما نسخه ی SQL ای که استفاده می کنید را ذکر کنید!
مقدمه ای از جداول موقت و متغیرهای جدولی:
جداول موقت (temporary) جداولی هستند که در بانک tempdb موقتا ذخیره می شوند این جداول را می توانیم با قرار دادن کاراکتر # قبل از اسم جدول ایجاد کنیم، ساخت این نوع از جداول کاملا مشابه با جداول اصلی هستند.


CREATE TABLE #TemporaryTable
(
a INT PRIMARY KEY,
b VARCHAR NOT NULL
)


متغیر های جدولی کاملا مشابه به متغیرهای دیگر هستند در واقع، هر متغیری پس از تعریف شدن یک حافظه از RAM به آن اختصاص داده می شود. برای تعریف متغیرهای جدولی شبیه به متغیرهای دیگر عمل کرده و نوع آن را table قرار می دهیم. همانطوری که ذکر شد بزرگترین تفاوت این نوع جداول با جداول دیگر (موقت و اصلی) در این است که این جداول در حافظه اصلی قرار می گیرند پس فضایی در دیسک سخت به آنها اختصاص داده نمی شود و این موضوع تبعا محدودیت هایی را برای آن به وجود می آورد. متغیر های جدولی می توانند جایگزین خوبی برای جداول موقت باشند.


DECLARE @TableVariable TABLE
(
a INT PRIMARY KEY,
b VARCHAR NOT NULL
)


در اینجا قصد داریم به شما چگونگی پست کردن کد و داده هایتان را در تالار نشان دهیم.
راه صحیح برای پست کردن داده ها
ابتدا بهتر است که به مزیت تولید و ارسال ساختار جدول(جداول) و داده هایمان به پردازیم:
1. ساختار جدول نمایان نوع داده ها (data type) جدول شما خواهد بود پس به بسیاری از سوالات غیر ضروری پاسخ خواهد داد
2. ساختار جدول، کلید اصلی (PK)، انواع شروط (CHECK) و... را مشخص می کند
3. توجه افرادی را که ممکن است بتوانند در حل مشکل شما کمکتان کنند را جلب خواهد کرد
4. داده های شما نمونه های خوبی از محیط واقعی شما هستند و می توانند برای هر چه سریعتر رسیدن به یک result مناسب مورد استفاده قرار بگیرند
ساخت script کامل جداول و داده ها
سه روش وجود دارد که شما بتوانید داده ها و ساختار جداول خود را تولید و ارسال کنید:
1. نوشتن دستورات INSERT و CREATE TABLE به طور دستی.
2. استفاده از Generate Scripts مربوط به database
3. استفاده از Data Generator برای تولید دستورات INSERT
روش اول: این روش وقت زیادی را از شما خواهد گرفت، فرض کنید جدول شما دارای چند ستون از انواع تاریخ و زمان، پول و اعداد طولانی می باشد پس شما مجبور خواهید بود که تمام این داده ها را بطور دستی بنویسید.
روش دوم: با استفاده از این روش شما بسادگی می توانید از جدول خود Script تهیه کنید. در نسخه های قبل از 2008 شما نمی توانید داده های خود را نیز تولید کنید، منظور تبدیل سطرهای جدول به دستورات DDL یعنی INSERT می باشد. ولی در نسخه ی 2008 این قابلیت به برنامه SQL Server افزوده شده است.
در SQL Server 2005/2008 برای گرفتن Script از جدول و داده ها دو راه وجود دارد:
راه اول: راست کلیک بر روی جدول (در قسمت ساختار درختی اشیاء) انتخاب منوی Script Table as سپس انتخاب گزینه CREATE To à New Query Editor Window .
راه دوم: راست کلیک بر روی یکی از بانک های موجود بر روی SQL Server، انتخاب منوی Tasks، انتخاب گزینه Generate Scripts سپس با کمک پنجره Wizard ظاهر شده شما به راحتی می توانید بانک و جدول خود را انتخاب کنید و Script مورد نظر را تولید کنید. مراحل به اینگونه است:
در اولین مرحله (Select Database) شما می توانید از لیست موجود یکی از بانک های اطلاعاتی که در نمونه ی نصب شده وجود دارند را انتخاب کنید.
در مرحله بعدی (Choose Script Options) گزینه Script Data را به True تنظیم کنید. (توجه کنید که این گزینه تنها در نسخه 2008 می باشد)
در مرحله بعدی (Choose Object Types) در این بخش شما می توانید انواع اشیایی که می خواهد از آنها Script تهیه کنید را انتخاب کنید
موقعی که جدول را در مرحله قبلی انتخاب کرده باشیم، در این مرحله (Choose Tables) لیست جداولی که قبلا ایجاد شده اند ظاهر خواهند شد شما می توانید هر کدام را که احتیاج دارید انتخاب کنید
مرحله Output Optionاین مرحله به شما اجازه می دهد که حالت خروجی مورد نظر را انتخاب کنید که به طور پیش فرض در حالت Script to New Query Window می باشد.
روش سوم:
این روش زمانی مورد استفاده قرار می گیرد که نسخه ی SQL Server شما 2000 یا 2005 باشد.
راه حل های مختلفی برای این کار وجود دارد که در اینجا به یکی از آنها پرداخته می شود (حتی شما می توانید با استفاده از SP ضمیمه شده ی تاپیک فقط با دادن نام جدول دستورات درج سطرهای جدولتان را دریافت کنید)
دستورات DDL مربوط به ساخت یک جدول:
ما برای ساخت جدول پیش رو از جدول موقت استفاده می کنیم.


--===== If the test table already exists, drop it
IF OBJECT_ID('TempDB..#mytable','U') IS NOT NULL
DROP TABLE #mytable

--===== Create the test table with
CREATE TABLE #mytable
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
DateValue DATETIME,
Value DECIMAL(9,4),
YearValue INT,
MonthValue INT
)

--===== Setup any special required conditions especially where dates are concerned
SET DATEFORMAT DMY


تابع OBJECT_ID یک نام object دریافت کرده و در صورت وجود آن شی id آن را بر می گرداند و در غیر این صورت مقدار NULL را بر می گرداند. از این تابع برای تشخیص موجودیت اشیاء (exists) استفاده می شود. البته استفاده از این تابع ضروری نیست بلکه از query زیر نیز می توانید استفاده کنید:


IF EXISTS (SELECT *
FROM sysobjects
WHERE NAME='TempDB..#mytable'
AND xtype='U')-- U = Table (user-defined)
DROP TABLE #mytable


IF EXISTS (SELECT *
FROM sys.objects
WHERE [object_id]=object_id('TempDB..#mytable')
AND type='U')-- U = Table (user-defined)
DROP TABLE #mytable


و دستور SET DATEFORMAT ترتیب ورود بخشهای تاریخ (ماه،روز،سال) را برای داده های datetime و smalldatetime مشخص می کند.


ساخت داده های جدول با استفاده از Data Generator
مناسب ترین راه برای ارسال داده ها فقط SELECT کردن داده ها از جدول واقعی است. یکی از مزیت های استفاده از داده های محیط واقعی این است افرادی که سعی در حل مشکل شما دارند بیهوده تلاش نخواهند کرد و شما در کمترین زمان بهترین جواب را خواهید گرفت.
تنها با یک تلاش اندک شما می توانید query هایی ایجاد کنید که خروجی آن دستوراتی برای درج سطرهای جدول باشند. ( دقت کنید که برای استفاده و اجرای خروجی از result to text استفاده می کنیم برای تنظیم می توانید پس از انتخاب پنجره query از منوی Query در قسمت Result to گزینه Result to Text را انتخاب کنید یا برای تنظیمات بیشتر از Query Option استفاده کنید)
به query زیر توجه کنید:


SELECT 'SELECT '
+ '''' + CAST(ID AS VARCHAR) + '''' + ','
+ '''' + CAST(DateValue AS VARCHAR) + '''' + ','
+ '''' + CAST(Value AS VARCHAR) + '''' + ','
+ '''' + CAST(YearValue AS VARCHAR) + '''' + ','
+ '''' + CAST(MonthValue AS VARCHAR) + '''' + ','
+ ' UNION ALL'
FROM #mytable


البته با استفاده از تابع QUOTENAME (نقل قول) این کار را ساده تر می توانیم انجام دهیم به مثال زیر توجه کنید:


SELECT 'SELECT '
+ QUOTENAME(ID,'''') +','
+ QUOTENAME(DateValue,'''')+','
+ QUOTENAME(Value,'''') +','
+ QUOTENAME(YearValue,'''')+','
+ QUOTENAME(MonthValue,'''')
+ ' UNION ALL'

FROM #mytable



اگر query های بالا را در یک query analyzer اجرا کنید، چیزی شبیه به خروجی زیر را تولید خواهند کرد:



SELECT '4','Oct 17 2007 12:00AM','5.1709','8','1' UNION ALL
SELECT '37','Oct 17 2007 12:00AM','5.5319','17','8' UNION ALL
SELECT '44','Oct 17 2007 12:00AM','5.5793','21','11' UNION ALL
SELECT '54','Oct 17 2007 12:00AM','5.2471','9','2' UNION ALL
SELECT '55','Oct 17 2007 12:00AM','5.1177','7','0' UNION ALL
SELECT '81','Oct 17 2007 12:00AM','5.5510','18','9' UNION ALL
SELECT '86','Oct 17 2007 12:00AM','5.5128','16','7' UNION ALL

SELECT '96','Oct 17 2007 12:00AM','5.5758','20','10' UNION ALL





آخرین UNION ALL موجود در عبارت فوق را باید حذف کنید و عبارت ضروری SET برای درج درون یک ستون از نوع IDENTITY مورد نیاز است و در پایان گزاره INSERT را قرار می دهیم که کد ما به شکل زیر در خواهد آمد.

توجه کنید که به طور مستقیم نمی توانیم یک مقدار را در ستون از نوع IDENTITY درج کنیم اگر سعی در این کار کنیم پیام خطایی به شکل زیر داده می شود

Cannot insert explicit value for identity column in table



--===== All Inserts into the IDENTITY column
SET IDENTITY_INSERT #mytable ON


--===== Insert the test data into the test table
INSERT INTO #mytable
(ID, DateValue, Value, YearValue, Monthvalue)
SELECT '4','Oct 17 2007 12:00AM','5.1709','8','1' UNION ALL
SELECT '37','Oct 17 2007 12:00AM','5.5319','17','8' UNION ALL
SELECT '44','Oct 17 2007 12:00AM','5.5793','21','11' UNION ALL
SELECT '54','Oct 17 2007 12:00AM','5.2471','9','2' UNION ALL
SELECT '55','Oct 17 2007 12:00AM','5.1177','7','0' UNION ALL
SELECT '81','Oct 17 2007 12:00AM','5.5510','18','9' UNION ALL
SELECT '86','Oct 17 2007 12:00AM','5.5128','16','7' UNION ALL
SELECT '96','Oct 17 2007 12:00AM','5.5758','20','10'


--===== Set the identity insert back to normal
SET IDENTITY_INSERT #mytable OFF



مشکل با برخی از انواع داده ها

نوع داده Money و برخی دیگر نمی توانند به شکل رشته ای در ستون مورد نظر درج شوند، حالا باید چه کار انجام دهیم؟ پاسخ ساده است کافی است که عبارت های نقل قول را حذف کنیم
فرض کنید ستون Value از جدول ذکر شده در این مقاله از نوع Money بوده باشد کافی است که به جای خطوط مورد نظر در query ها از خط زیر استفاده شود:


+ CAST(Value AS VARCHAR)+','



در پایان کدهای ما باید چگونه شده باشد




--===== If the test table already exists, drop it
IF OBJECT_ID('TempDB..#mytable','U') IS NOT NULL
DROP TABLE #mytable


--===== Create the test table with
CREATE TABLE #mytable
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED, --Is an IDENTITY column on real table
DateValue DATETIME,
Value MONEY,
YearValue INT,
Monthvalue INT
)


--===== Setup any special required conditions especially where dates are concerned
SET DATEFORMAT DMY -- Day&Month&Year


--===== All Inserts into the IDENTITY column
SET IDENTITY_INSERT #mytable ON


--===== Insert the test data into the test table
INSERT INTO #mytable
(ID, DateValue, Value, YearValue, Monthvalue)
SELECT '4','Oct 17 2007 12:00AM',5.1709,'8','1' UNION ALL
SELECT '37','Oct 17 2007 12:00AM',5.5319,'17','8' UNION ALL
SELECT '44','Oct 17 2007 12:00AM',5.5793,'21','11' UNION ALL
SELECT '54','Oct 17 2007 12:00AM',5.2471,'9','2' UNION ALL
SELECT '55','Oct 17 2007 12:00AM',5.1177,'7','0' UNION ALL
SELECT '81','Oct 17 2007 12:00AM',5.5510,'18','9' UNION ALL
SELECT '86','Oct 17 2007 12:00AM',5.5128,'16','7' UNION ALL
SELECT '96','Oct 17 2007 12:00AM',5.5758,'20','10'


--===== Set the identity insert back to normal
SET IDENTITY_INSERT #mytable OFF



اگر تعداد ستون های ما زیاد باشد یا کلا وقت کافی برای ساخت این چنین query هایی نداشته باشیم آیا تابع یا SP وجود دارد که با دادن نام جدول دستورات INSERT را برایمان تولید (Generate) کند؟

جواب مثبت است با استفاده از SP ضمیمه شده در تاپیک شما می توانید به این مهم دست یابید.
منبع:


http://www.sqlservercentral.com/articles/Best+Practices/61537/ (http://www.sqlservercentral.com/articles/Best+Practices/61537/)




http://www.sqlservercentral.com/articles/T-SQL/66987/ (http://www.sqlservercentral.com/articles/T-SQL/66987/)
http://www.kodyaz.com/articles/sql-server-script-data-with-generate-script-wizard.aspx (http://www.kodyaz.com/articles/sql-server-script-data-with-generate-script-wizard.aspx)