首页  >  文章  >  数据库  >  SQL2005CLR函数扩展

SQL2005CLR函数扩展

WBOY
WBOY原创
2016-06-07 16:16:50960浏览

本文只是一个山寨试验品,思路仅供参考. -------------------------------------------------------------------------------- 原理介绍: 索引建立 目 录结构划分方案也只是很简易的实现了一下,通过unicode把任意连续的两个字符(中文或英文)分为4个字节来做四

本文只是一个山寨试验品,思路仅供参考.
--------------------------------------------------------------------------------
原理介绍:
索引建立
目 录结构划分方案也只是很简易的实现了一下,通过unicode把任意连续的两个字符(中文或英文)分为4个字节来做四层目录,把索引的内容对应的主关键字 (主要为了使用sql索引和唯一性)作为文件名,两个字符在索引内容中的位置作为文件后缀来存储.文件本身为0字节,不保存任何信息.

比如一条数据 "pk001","山寨索引"
山寨索引 四个字的unicode为
[0]: 113
[1]: 92
[2]: 232
[3]: 91
[4]: 34
[5]: 125
[6]: 21
[7]: 95
那么对应的文件结构为
../113/92/232/91/pk001 .0
../232/91/34/125/pk001 .1
../34/125/21/95/pk001 .2

索引使用
比如搜索"寨索引 "
则搜索 "../232/91/34/125/" 目录下的所有文件,然后根据 pk001 .1的文件后缀名1,去看 ../34/125/21/95/pk001.2文件是否存在.依次类推,最后返回一个结果集.
--------------------------------------------------------------------------------
实用性
具 体的实用性还有待验证.这只是实现了精确的like搜索,而不能做常见搜索引擎的分词效果.另外海量数据重建索引的性能也是面临很严峻的问题,比如cpu 负载和磁盘io负载.关于windows一个目录下可以保持多少个文件而不会对文件搜索造成大的性能损失也有待评估,不过这个可以考虑根据主键的文件名 hash来增加文件目录深度降低单一目录下的文件数量.
--------------------------------------------------------------------------------
演示效果
实现了针对test标的name和caption两个字段作索引搜索.

-- 设置和获取索引文件根目录
--select dbo.xfn_SetMyIndexFileRoot('d:/MyIndex')
--select dbo.xfn_GetMyIndexFileRoot()
-- 建立测试环境
go
create table test( id uniqueidentifier , name nvarchar ( 100), caption nvarchar ( 100))
insert into test select top 3 newid (), ' 我的索引 ' , ' 测试 ' from sysobjects
insert into test select top 3 newid (), ' 我的测试 ' , ' 索引 ' from sysobjects
insert into test select top 3 newid (), ' 测试索引 ' , ' 测试索引 ' from sysobjects
insert into test select top 3 newid (), ' 我的索引 ' , ' 索引 ' from sysobjects
create index i_testid on test( id)
-- 建立索引文件
declare @t int
select @t=
dbo. xfn_SetKeyForMyIndex( id, 'testIndex' , name ' ' caption)
from test
-- 查询数据
select a.* from test a, dbo. xfn_GetKeyFromMyIndex( '测试 索引 我的' , 'testIndex' ) b
where a. id= b. pk
/*
0C4634EA-DF94-419A-A8E5-793BD5F54EED 我的索引 测试
2DD87B38-CD3F-4F14-BB4A-00678463898F 我的索引 测试
8C67A6C3-753F-474C-97BA-CE85A2455E3E 我的索引 测试
C9706BF1-FB1F-42FB-8A48-69EC37EAD3E5 我的测试 索引
8BBF25CC-9DBB-4FCB-B2EB-D318E587DD5F 我的测试 索引
8B45322D-8E46-4691-961A-CD0078F1FA0A 我的测试 索引
*/
--drop table test
--------------------------------------------------------------------------------
clr代码如下:编译为MyFullIndex.dll

复制代码 代码如下:


使用系统;
使用 System.Data.SqlTypes;
使用 Microsoft.SqlServer.Server;
使用系统集合;
使用 System.Collections.Generic;
公共分部类 UserDefinedFunctions
{
///
/// 设置索引目录
///
/// <参数名称=“值”>
/// ;
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlBoolean SetRoot(SqlString value)
{
if (value.IsNull) 返回 false ;
if (System.IO.Directory .Exists(value.Value))
{
根=值.值;
返回真;
}
否则
{
返回假;
}
}
///
/// 获取索引目录
///
/// ;
[Microsoft.SqlServer.Server.SqlFunction]
公共静态 SqlString GetRoot()
{
返回新的SqlString(根);
}
///
/// 建立索引
///
/// 主键参数>
/// 索引名称
/// 索引内容
/// ;
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlInt32 SetIndex(SqlString key,SqlString indexName,SqlString content)
{
if (key.IsNull || content.IsNull||indexName.IsNull) 返回 0;
return _setIndex(key.Value,indexName.Value, content.Value);
}

///
/// 查询索引
///
/// 关键字(空格分隔)
/// 索引名称
/// ;
[SqlFunction (TableDefinition = "pk nvarchar(900)" , Name = "GetIndex" , FillRowMethodName = "FillRow" )]
public static IEnumerable GetIndex(SqlString word,SqlString indexName)
{

System.Collections.Generic.List ret = new List ();
if (word.IsNull || indexName.IsNull) 返回 ret;
return _getIndex2(word.Value, indexName.Value);
}

public static void FillRow(Object obj, out SqlString pk)
{
字符串键 = obj.ToString();
pk = 密钥;
}
静态字符串根 = @"d:/index" ;

///
/// 获取有空格分隔的索引信息
///
/// ;
/// ;
/// ;
静态 System.Collections.Generic.List ; _getIndex2(字符串单词, 字符串索引名称)
{
string [] arrWord = word.Split(new char [] { ' ' }, StringSplitOptions .RemoveEmptyEntries);

System.Collections.Generic.List key_0 = _getIndex(arrWord[0], indexName);

if (arrWord.Length == 0) 返回 key_0;
System.Collections.Generic.List [] key_list=new List [arrWord.Length-1];
for (int i = 0; i {
System.Collections.Generic.List key_i = _getIndex(arrWord[i 1],indexName);
key_list[i] = key_i;
}

for (int i=key_0.Count-1;i>=0;i--)
{
foreach (System.Collections.Generic.List key_i in key_list)
{
if (key_i.Contains(key_0[i]) == false )
{
key_0.RemoveAt(i);
继续 ;
}
}
}
返回键_0;
}
///
/// 获取单个词的索引信息
///
/// ;
/// ;
/// ;
静态 System.Collections.Generic.List ; _getIndex(字符串单词, 字符串索引名称)
{
System.Collections.Generic.List ret = new List ();
byte [] bWord = System.Text.Encoding .Unicode.GetBytes(word);
if (bWord.Length
字符串路径 = string .Format(@"{0}/{1}/{2}/{3}/{4}/{5}/" , root,indexName, bWord[0], bWord[1], bWord [2],bWord[3]);
if (System.IO.Directory .Exists(path) == false )
{
返回ret;
}
字符串[] arrFiles = System.IO.Directory .GetFiles(path);

foreach(arrFiles 中的字符串文件)
{
字符串键 = System.IO.Path .GetFileNameWithoutExtension(file);
字符串索引 = System.IO.Path .GetExtension(file).TrimStart(new char [] { '.' });
int cIndex = int .Parse(index);
布尔 bHas = true ;
for (int i = 2; i {
string nextFile = string .Format(@"{0}/{1}/{2}/{3}/{4}/{5}/{6}.{7}" ,
root, indexName, bWord[i 0], bWord[i 1], bWord[i 2], bWord[i 3], key, cIndex);

if (System.IO.File .Exists(nextFile) == false )
{
bHas=假;
休息 ;
}
}
if (bHas == true &&ret.Contains(key)==false )
ret.Add(key);

}
返回ret;
}

///
/// 建立索引文件
///
/// ;
/// ;
/// 参数>;
/// ;
static int _setIndex(字符串键,字符串索引名,字符串内容)
{
byte [] bContent = System.Text.Encoding.Unicode.GetBytes(content);
if (bContent.Length for (int i = 0; i {
字符串路径 = string .Format(@"{0}/{1}/{2}/{3}/{4}/{5}/" , root,indexName, bContent[i 0], bContent[i 1] , bContent[i 2], bContent[i 3]);
if (System.IO.Directory .Exists(path) == false )
{
System.IO.Directory .CreateDirectory(路径);
}
string file = string .Format(@"{0}/{1}.{2}" , 路径, 键, i / 2);

if (System.IO.File .Exists(file) == false )
{
System.IO.File.Create(文件).Close();
}
}
返回内容.长度;
}
};

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn