PDA

View Full Version : سوال: ورود کاراکتر اضافی به دیتابیس



amir_ir
شنبه 28 شهریور 1388, 08:19 صبح
سلام به همه دوستان
فیلدی در sql 2005 به صورت(15)Nvarchar تعریف شده و با استفاده از کد زیر مقادیر رو وارد دیتابیس می کنم ولی یک مشکل بوجود میاد و اون اینکه مثلا اگر مقدار ورودی 5 کاراکتر باشه ، کل 15 کاراکتر در دیتابیس اشغال میشه. یعنی 5 کارکتر که کاربر وارد کرده بود و 10 کاراکتر هم space وارد میشه و کل 15 کاراکتر اشغال میشه.حتی از Trim هم استفاده کردم که space ها رو حذف کنم ولی جواب نمیده .
ممنون میشم منو راهنمایی کنید .



FrmDMTransport.ADOQFixCar.SQL.Clear;
FrmDMTransport.ADOQFixCar.SQL.Add('Insert into Fix_Car(FixNo,Pelak) values(:fn,:pe) ');
FrmDMTransport.ADOQFixCar.Parameters.ParamByName(' fn').Value:=trim(TxtFixNo.Text);
FrmDMTransport.ADOQFixCar.Parameters.ParamByName(' pe').Value:=trim(TxtPelak.Text);
FrmDMTransport.ADOQFixCar.ExecSQL;

bootshow
شنبه 28 شهریور 1388, 14:28 عصر
از کجا فهمیدی که 15 کاراکتر اشغال میکنه؟؟!!!
درسته اگر در دیتابیس فقط یک فیلد را هم وارد کنی به اندازه تمام فیلدها در دیتابیس حجم اشغال میکنه.مگر اینکه از compression استفاده کنی یا اینکه از blob استفاده کنی.مطمئن نیستم جواب بده یا نه. ولی کلا دیتابیس این کارو بخاطر افزایش سرعت انجام داده و استفاده از دو روش بالا سرعت کار با دیتابیس را کم میکنه

Saeed_m_Farid
شنبه 28 شهریور 1388, 15:23 عصر
چرا اینقدر به پارامتر علاقه دارین؟ اینطوری trace کردن کدتون هم سخت تر میشه، راحت کد زیر رو بنویسید تا ببینید شاید با Space واقعاً داره میره واسه INSERT ، من SQL رو ShowMessage میکنم(مشکل رو متوجه شدین برش دارین) :
with FrmDMTransport.ADOQFixCar do begin
SQL.Text := 'INSERT INTO Fix_Car(FixNo,Pelak) VALUES('
+ TxtFixNo.Text + ',' + TxtPelak.Text + ')';
ShowMessage(SQL.Text);
ExecSQL;
end;

amir_ir
یک شنبه 29 شهریور 1388, 11:47 صبح
چرا اینقدر به پارامتر علاقه دارین؟ اینطوری trace کردن کدتون هم سخت تر میشه، راحت کد زیر رو بنویسید تا ببینید شاید با Space واقعاً داره میره واسه INSERT ، من SQL رو ShowMessage میکنم(مشکل رو متوجه شدین برش دارین) :
with FrmDMTransport.ADOQFixCar do begin
SQL.Text := 'INSERT INTO Fix_Car(FixNo,Pelak) VALUES('
+ TxtFixNo.Text + ',' + TxtPelak.Text + ')';
ShowMessage(SQL.Text);
ExecSQL;
end;


سلام سعید جان
ممنون از راهنمایی های خوبت . syntax هایی که استفاه میکنی خیلی روان و راحت هست.
کد بالا جواب داد و چک کردم و دیگه کاراکتر اضافی وارد دیتابیس نمیشه. اما 1 سوال دیگه:
اگر یکی از فیلدها از جنس Float بود ، به چه شکل میشه توی کد بالا اونو Cast کرد؟؟؟
فرض کن '+TxtFixNo.Text+' رو بخوای توی کد زیر به float تبدیل کنی.


SQL.Text := 'INSERT INTO Fix_Car(FixNo,Pelak) VALUES('
+ TxtFixNo.Text + ',' + TxtPelak.Text + ')';

---------------------
سوال2)
( StrToFloatDef(Edit1.Text, -1) >= 0 ) به چه معنی هست؟ چیو چک میکنه؟

خیلی ممنون از لطف همه دوستان

vcldeveloper
دوشنبه 30 شهریور 1388, 00:52 صبح
چرا اینقدر به پارامتر علاقه دارین؟
برای اینکه در اجراهای بعدی کوئری performance بالاتری داره، و SQL نیازی نداره که هر بار این کوئری را Parse کنه.

Saeed_m_Farid
دوشنبه 30 شهریور 1388, 09:47 صبح
...
اگر یکی از فیلدها از جنس Float بود ، به چه شکل میشه توی کد بالا اونو Cast کرد؟؟؟
فرض کن '+TxtFixNo.Text+' رو بخوای توی کد زیر به float تبدیل کنی.


SQL.Text := 'INSERT INTO Fix_Car(FixNo,Pelak) VALUES('
+ TxtFixNo.Text + ',' + TxtPelak.Text + ')';
---------------------
سوال2)
( StrToFloatDef(Edit1.Text, -1) >= 0 ) به چه معنی هست؟ چیو چک میکنه؟ ...



اون یه جای دیگه بود که تبدیل نوع لازم داشتیم، یعنی این تاپیک (http://barnamenevis.org/forum/showthread.php?p=807805#post807805)؛ تو این کدی که آوردین، دقیقاً همون چیزی که تو Edit ها هست تو SQL موردنظر جایگزین میشه و نیاز به Type Cast نیست، درسته به دلفی مربوط نمیشه ولی اگه می خواهید چگونگی تبدیل نوع تو SQL-Server رو بدونید، همونطورکه میدونید دو تا تابع اصلی واسه اینکار هست، یعنی CAST و CONVERT با این سینتکس :

Using CAST:

CAST ( expression AS data_type )

Using CONVERT:

CONVERT ( data_type [ ( length ) ] , expression [ , style ] )

ولی معنی نداره که یه مقدار (نه یه فیلد) رو CAST کنید! برای روشن شدن منظورم، کار شما مثل نوشتن کد زیر هست :

SELECT CAST(123 AS Float) FROM Customers

StrToFloatDef تابع تبدیل رشته به Float هست که در صورت بروز خطا پارامتر دوم رو بر می گردونه، به این معنی که بررسی میکنه که مقدار موردنظر درون Edit1.Text قابل تبدیل به Float هست یا نه؟ مثلاً واسه 'a123sd211' مقدار 1- بر می گرده و چون مقدار برگشتی کوچک تر از صفر هست داخل شرط نمیره و ... البته همونطوری که اونجا گفتم (http://barnamenevis.org/forum/showpost.php?p=807805&postcount=4) تو این مورد خاص، به شرطی که مقدار موردنظر منفی نباشه، چون امکان داشتن سرعت منفی برای ماشین منتفی هست.

Saeed_m_Farid
دوشنبه 30 شهریور 1388, 10:04 صبح
برای اینکه در اجراهای بعدی کوئری performance بالاتری داره، و SQL نیازی نداره که هر بار این کوئری را Parse کنه.
راستش متوجه نشدم منظورتون از "Parse کردن SQL در اجراهای بعدی" چیه؟ اگه منظورتون Parse کردن یه کوئری ثابت SQL-Server مثلاً تو یه حلقه دلفی هست، چطور استفاده از پارامتر میتونه مانع پارس شدن مجدد کوئری موردنظر بشه (چه فرقی با یه expressionساده -از نظر دلفی String- داره)؟ اصلاً در مورد دلفی داریم صحبت می کنیم یا SQL-Server؟ میشه یه کم بیشتر توضیح بدین؟

vcldeveloper
سه شنبه 31 شهریور 1388, 01:02 صبح
راستش متوجه نشدم منظورتون از "Parse کردن SQL در اجراهای بعدی" چیه؟ اگه منظورتون Parse کردن یه کوئری ثابت SQL-Server مثلاً تو یه حلقه دلفی هست، چطور استفاده از پارامتر میتونه مانع پارس شدن مجدد کوئری موردنظر بشه (چه فرقی با یه expressionساده -از نظر دلفی String- داره)؟ اصلاً در مورد دلفی داریم صحبت می کنیم یا SQL-Server؟ میشه یه کم بیشتر توضیح بدین؟
وقتی یک کوئری در SQL Server اجرا میشه، دستورات موجود در آن را Parse میکنه، و براش Execution Plan .
در نظر میگیره.
اگر کوئری با استفاده از پارامتر نوشته شده باشه، SQL Server داده های باینری حاصل از پردازش کوئری را در سرور نگهداری میکنه. در این صورت، در اجراهای بعدی اون کوئری، دیگه نیازی به ارسال کل دستور SQL و پردازش آن نیست، فقط مقادیر پارامترها به سرور ارسال میشند، و سرور هم پارامترها را در کد باینری ایی که از قبل موجود هست، جایگزاری میکنه. یعنی در این شرایط، اجرای اون کوئری از دفعه دوم به بعد مثل اجرای یک Stored Procedure هست. برای همین هم کارایی بیشتری داره.

Saeed_m_Farid
سه شنبه 31 شهریور 1388, 16:33 عصر
...


اگر کوئری با استفاده از پارامتر نوشته شده باشه، SQL Server داده های باینری حاصل از پردازش کوئری را در سرور نگهداری میکنه.
در این صورت، در اجراهای بعدی اون کوئری، دیگه نیازی به ارسال کل دستور SQL و پردازش آن نیست، فقط مقادیر پارامترها به سرور ارسال میشند، و سرور هم پارامترها را در کد باینری ایی که از قبل موجود هست، جایگزاری میکنه.
یعنی در این شرایط، اجرای اون کوئری از دفعه دوم به بعد مثل اجرای یک Stored Procedure هست. برای همین هم کارایی بیشتری داره.

خیلی ممنون آقای کشاورز :
ولی جواب شما ابهامات من رو بیشتر کرد!


برای این کار که شما می فرمایید باید یه پروتکل واسط بین اشیاء ADO و SQL-Server برقرار باشه، و چون ADO تنها با SQL Server ارتباط نداره پس Oracle، PostgreSQL، MySQL و ... هم باید یه جوری همچین خاصیتی رو پشتیبانی کنند، من نمیتونم تصور کنم اگه قرار باشه اوراکل چندین میلیون رکورد رو بصورت باینری تو سرور نگه داره که ببینه من دفعه بعد چه پارامتری میخوام بهش پاس بدم، چه اتفاقی میافته! همین موضوع واسه SQL-Server هم بنظرم صادقه ... فکر کنم منظورتون از "داده های باینری حاصل از پردازش کوئری" نتیجه پرسش ما نباشه و کد کامپایل شده کوئری هست که اونوقت بحث آخری منتفیه ولی نیاز به پروتکلی برای ارتباط پارامتریک با پایگاه (واسه همه بانک ها جواب بده)، همچنان پابرجاست.



مگه کل دستور SQL چقدره؟ فوقش اینه چند تا UNION بین جداول و شروط مختلف و ... که هرجور هم که باشه یه Plain text هست، پس فرستادنش همچین هزینه ای به برنامه یا پایگاه تحمیل نمی کنه، در مورد پردازش SQL هم، در قیاس با حجم عظیم داده ای که قراره تحلیل بشه، چندان محسوس نیست، مهمتر اینکه با این تنوع بانک های اطلاعاتی، موتور پایگاه داده چطور میفهمه که کلاینت، مثلاً SQL پارامتریک واسش فرستاده؟ تا کی کد باینری تولید شده برای SQL پارامتردار رو نگهداری می کنه؟ چطوری Listen میشه به فرستنده Sql موردنظر که پارامتر بفرسته؟ چطوری تو کد باینری پارامتر جایگزین میکنه؟ و ... درنهایت داده ها باید دوباره واکشی بشن و از لحاظ داده، فرقی نمی کنه که SQL کامپایل شده باشه یا نه، فقط همون زمان کامپایل یکمی تفاوت میکنه.



خلاصه اش اینکه در مورد واکشی داده فکر نمی کنم اصلاً تفاوتی بکنه که SQL Statement کامپایل شده باشه یا نه، یعنی SQL روی یه مجموعه محدود شده ای از داده ها اعمال نمیشه و با سرورهای قدرتمندی که معمولاً برای پایگاه داده ها تهیه میشه، مدت زمان پارس SQL کاملاً قابل چشم پوشی هست ...

vcldeveloper
سه شنبه 31 شهریور 1388, 23:20 عصر
برای این کار که شما می فرمایید باید یه پروتکل واسط بین اشیاء ADO و SQL-Server برقرار باشه، و چون ADO تنها با SQL Server ارتباط نداره پس Oracle، PostgreSQL، MySQL و ... هم باید یه جوری همچین خاصیتی رو پشتیبانی کنند، من نمیتونم تصور کنم اگه قرار باشه اوراکل چندین میلیون رکورد رو بصورت باینری تو سرور نگه داره که ببینه من دفعه بعد چه پارامتری میخوام بهش پاس بدم، چه اتفاقی میافته! همین موضوع واسه SQL-Server هم بنظرم صادقه ... فکر کنم منظورتون از "داده های باینری حاصل از پردازش کوئری" نتیجه پرسش ما نباشه و کد کامپایل شده کوئری هست که اونوقت بحث آخری منتفیه ولی نیاز به پروتکلی برای ارتباط پارامتریک با پایگاه (واسه همه بانک ها جواب بده)، همچنان پابرجاست.
لزومی نداره همه بانک های اطلاعاتی که ذکر کردید از این قابلیت بهره ببرند. باید درایور ADO ایی که این بانک ها ارائه می کنند این قابلیت را داشته باشه. ADO رابط برنامه نویسی یکسانی برای بانک های اطلاعاتی مختلف ارائه میکنه، این به معنی آن نیست که هر بانکی که درایور ADO دارد، امکاناتی مشابه سایر بانک ها دارد. درایوری که یک بانک برای اتصال ADO ارائه میکنه، توانایی های آن را مشخص میکنه.

همچنین، قرار نیست اوراکل یا SQL Server چند میلیون رکورد را در حافظه نگهداری کنند. قبلا هم گفتم که این قابلیت باعث میشه که کوئری مربوطه دقیقا مثل یک Stored Procedure ذخیره شده در سمت سرور عمل کنه. مگه الان بابت هر SP ایی که در سرور می نویسید، بانک اطلاعاتی رکوردهای آن را در حافظه نگهداری میکنه؟! پردازش فرامین SQL رسیده، و تعیین Execution Plan مناسب کار چندان ساده ایی نیست، و به تناسب میزان پیچیدگی کوئری ارسالی، توان قابل ملاحظه ایی از سرور میگیره. شاید این مقدار در مقایسه با حجم داده های ارسالی به کلاینت چندان نباشه، ولی در نوع خودش قابل توجه هست.

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

Saeed_m_Farid
چهارشنبه 01 مهر 1388, 17:22 عصر
لزومی نداره همه بانک های اطلاعاتی که ذکر کردید از این قابلیت بهره ببرند.
اگر خیلی مایل هستید که بدونید ...
در هر حال این بحث ارتباطی با موضوع تاپیک نداره.



من واسه خودم نتیجه می گیرم که استفاده از این امکان با بعضی بانک ها سازگاره و با بعضی نه و تو اون یعضی دومی، با اونها مثل SQL معمولی رفتار میشه، پس همچین چیز استانداردی هم نیست.
نه، خیلی مایل نیستم؛ چون کار من یه چیز دیگه است ولی با پاسخ شما، واسم یه ابهامی در مورد پروتکل ارتباطی ADO-SQL پیش اومد که حالا هم از روی تنبلی! عطایش رو به لقایش بخشیدم.
چرا عصبانی میشید؟:چشمک: ببخشید خوب، روال پست هام از دستم در رفت ...