# پایگاه‌های داده > SQL Server > T-SQL >  بهترین روش جستجوی عبارت فارسی در SQlServer

## takavar_dez

با سلام

بهترین روش برای جستجوی یک کلمه فارسی در پایگاه داده چیه؟برای مثال اگه بخواهیم روی یکی از جداولمون با شرط اینکه ستون نام مساوی با کلمه "علی" و یا شامل اون باشه پرس و جو بزنیم آیا کد زیر درسته؟
البته این کد جواب نمیده و با وجود دیتای ارضا کننده شرط هیچ تاپلی برگشت داده نمیشه
لطفا توضیح بدید اشکال کار کجاست؟
با سپاس

Select *
From T_Test 
Where (Fname = N'علی') or (Fname like N'%علی%')

----------


## takavar_dez

این توضیح رو اضافه کنم که کدی که بالا گذاشتم برای کلمات انگلیسی هیچ مشکلی نداره اما من به جستجوی کلمات فارسی نیاز دارم!
چطور میشه مشکل کلمات فارسی در جستجو رو حل کرد؟! :متفکر:

----------


## یوسف زالی

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

----------


## takavar_dez

> سلام.
> مشکل شما احتمالا مربوط هست به Collation.
> کلماتی که در جدول هست با کلمه ای که سرچ می کنید فرق داره.
> خصوصا در ی و ک که عربی و فارسیش فرق داره.
> می تونی کدی ران کنی که اطلاعات دیتابیس رو درست کنه و از اون به بعد موقع اینسرت حواست به دیتا باشه که در ی و ک فرم استانداردی داشته باشه.
> تست کن. احتمالا می تونی کلمه حسن رو همین الان سرچ کنی. اگه تونستی و پیدا کرد حتما گیرت همینه.


درسته مشکل همینه ممنونم
چه جور کدی رو میشه برای حل این مشکل ران کرد تا وقت اینسرت اطلاعات اونجور که بخوایم ذخیره بشه؟

----------


## یوسف زالی

برای اینکه از این به بعد دچار این مشکل نشی ، باید قراردادی با خودت بگذاری:
کدوم ک و کدوم ی برای شما استاندارد محسوب می شه؟
برای مثال من اینجا فرض می کنم که استاندارد شما حروف فارسی هست و عربی ها باید به فارسی تبدیل بشن.
اونوقت موقع Insert اگر مثلا فیلد متنی شما نام باشد، به جای استفاده از Name باید بگذاریم
replace(Name,nchar(1603),nchar(1705)) -- jaye K arabi ro ba K farsi avaz mikonim

کد ک فارسی 1705 هست.
این کدها رو می تونی از دوراه بدست بیاری. برنامه CharMap ویندوز و خود SQL . مثلا این رو تست کن: 

select UniCode('X') -- kode harfe morede nazar

----------


## Galawij

و در ادامه ...
اگر قبلاً در بانک اطلاعاتیتون داده وارد کردید می تونید یک کرسر روی این دستور نوشته و در داخل یک روال فراخوانی کنید تا بانک اطلاعاتیتون به روز رسانی شود.
Exec(
'Update ['+@TableName+'] Set ['+@ColumnName+']=Replace(Replace(cast(['+@Columnname+']=As nvarchar(Max)),Nchar(1740),Nchar(1610)),Nchar(1705  ),Nchar(1603))'
)

----------


## takavar_dez

> و در ادامه ...
> اگر قبلاً در بانک اطلاعاتیتون داده وارد کردید می تونید یک کرسر روی این دستور نوشته و در داخل یک روال فراخوانی کنید تا بانک اطلاعاتیتون به روز رسانی شود.
> Exec(
> 'Update ['+@TableName+'] Set ['+@ColumnName+']=Replace(Replace(cast(['+@Columnname+']=As nvarchar(Max)),Nchar(1740),Nchar(1610)),Nchar(1705  ),Nchar(1603))'
> )


 دوست عزیز کرد من
ممنون از راهنماییتون 
من روی مفهوم کرسر مشکل اساسی دارم اصلا نمی فهمم چیه؟! یه توضیح خوب از کرسر می تونید ارائه بدید؟

----------


## Galawij

سلام 
هدف من از آن تکه کد این بود که خودتون بقیه راه را بریرد ولی مثل اینکه نیاز به توضیح بیشتر هست.
برای آموزش کرسر در همین سایت قبلاً توضیحاتی داده شده که می تونید به آن صفحات مراجعه کنید. برای مثال این لینک
ولی درادامه مابقی کد را با توضیحات براتون می ذارم.
در ابتدا دو متغیر برای نام جدول و نام ستون و یک متغیر از نوع کرسر تعریف می کنیم.
Declare @Table Nvarchar(500),@Col Nvarchar(500)
Declare @Table_Cursor Cursor
سپس ساختار دستور Select را برای کرسر با کلمه کلیدی For تعیین می کنید. در این دستور ما بین دو جدول سیستمی SysObject و SysColumns لیستی از ستون های با نوع داده های که برای کاراکتر می توان استفاده کرد واکشی می کنیم. دقیق به کدها نگاه کنید:

FOR
SELECT a.name,--table 
b.name --col 
FROM sysobjects a,
syscolumns b 
WHERE a.id = b.id 
AND a.xtype ='U'--User table 
AND(
b.xtype = 99 --ntext 
OR b.xtype = 35 -- text 
OR b.xtype = 231 --nvarchar 
OR b.xtype = 167 --varchar 
OR b.xtype = 175 --char 
OR b.xtype = 239 --nchar 
)

این دستور 'a.xtype ='U روی جداولی که کاربر در بانک اطلاعاتی ایجاد کرده است، مانور می دهد. به اعدادی که برای نوع داده های کاراکتری استفاده شده است دقت کنید ممکن است این نوع داده در ورژن ها مختلف از Sql متفاوت باشد می تونید برای مطمئن شده از درستی کدها یک Select از جدول سیستمی SysTypes بگیرید. 
متغییر کرسری را باز می کنید. و روی تک تک سطرها تا پایان رکوردها FETCH می کنید. با این دستورات :

OPEN Table_Cursor FETCHNEXTFROM Table_Cursor INTO @Table,@Col 
WHILE(@@FETCH_STATUS= 0)
BEGIN

حالا با استفاده از آن تکه کدی که نوشتم اقدام به Update جداولتون می کنید. 
و در نهایت متغیر را می بندید و حافظه اشغال شده توسط کرسر را آزاد می کنید. با این دستورات:

FETCHNEXTFROM Table_Cursor INTO @Table,@Col 
ENDCLOSE Table_Cursor DEALLOCATE Table_Cursor

خیلی سعی کردم با یک روش غیر از کرسر پیاده کنم جواب نداد.

----------


## یوسف زالی

سلام مجدد.
کرسر ها اشیایی هستند مثل اشاره گر موقعیت در فایل که به ردیف خاصی از یک سلکت اشاره می کنند.
اگر با فایل کار کرده باشید می دونید که پس از هر read اگر بار دیگه read کنید کاراکتر بعدی خونده میشه.
اما کی گفت که کاراکتر بعدی خونده شه؟ فقط گفتیم خونده شه.
قضیه اینه که در حافظه مربوط به کار با فایل اشاره گری موقعیت کاراکتری که باید خوانده شه رو نگه میداره و با هربار خوندن خودش اتوماتیک می ره جلو.
تو فایل های غیر متنی (باینری) هم میشد با دستور Seek بگیم این اشاره گر بره به کدوم کاراکتر اشاره کنه.

دقیقا اتفاقی که در کرسر می افته هم همین جوریه.
حالا با تفاوتهایی و پیشرفته شدن هایی..

اینجا می شه روی "ردیف" های یک "Select" اشاره گر گذاشت.

به چه دردی می خوره خب؟
گاهی کار ما به گونه ای هست که مجبوریم به ازای هر ردیف از یک سلکت خاص کاری انجام بدیم که نمی شه اون کار رو یکهو انجام داد.
مثال خیلی ساده اش اینه که ردیفی داریم برای جمع مانده های ردیف های بالایی. نمیشه با یک دستور آپدیت این کارو کرد. پس میایم و روی سلکتی از جدول مورد نظر که می خواهیم روش کاری کنیم(در این مثال همه ردیف ها) کرسر می گذاریم و در یک حلقه یکی یکی می ریم روی ردیف بعدی و کارمون رو روی ردیفی که هستیم انجام می دیم...

این مفهوم ساده کرسر هست.
ایشالا همین روزا یک توضیح جامع درست درمون براتون می گذارم ..

----------


## یوسف زالی

معمولا میشه هر کرسری رو به While تبدیل کرد.
اول در یک جدول موقتی میریزیم . سپس top 1 یکی یکی از آن بر می داریم.
توضیجات در پستهای بعدی... (الان سر کارم!)

----------


## takavar_dez

> ایشالا همین روزا یک توضیح جامع درست درمون براتون می گذارم ..


سلام
ممنونم حتما این کار رو بکنید لطفا

----------

