看此文档前,先参考一下文档 https://blog.csdn.net/downmoon/article/details/24374609

环境:阿里云ECS SQL Server 2017 + Delphi7

测试用xcopy,robocopy等命令迁移文件好像不太会用。

倒是可以通过T-SQL的方法,但是需要文件在服务器上面,这就有点难受了。如下:

--我们使用该函数插入一个图片文件到该目录下:这里的路径需要是服务器上的路径。
declare @image1 varbinary(max), @path_locator hierarchyid;
select @image1=cast(bulkcolumn as varbinary(max)) from openrowset(bulk N'C:\1.png', single_blob) as x;
select @path_locator=path_locator from DocumentStores where [name]='MyDir1';
insert into DocumentStores(name, file_stream, path_locator)
values('1.png', @image1, dbo.fnGetNewPathLocator(newid(), @path_locator)); --如果你想使用SQL Server本身提供的hierarchyid层次结构,下面这个函数也许可以帮你:
create FUNCTION fnGetNewPathLocator
(@child uniqueidentifier,
@parent hierarchyid)
returns hierarchyid
as
begin
declare @ret hierarchyid, @binid Binary(16) = convert(binary(16), @child);
select @ret=hierarchyid::Parse(
COALESCE(@parent.ToString(), N'/') +
CONVERT(nvarchar, CONVERT(bigint, SUBSTRING(@binId, 1, 6))) + N'.' +
CONVERT(nvarchar, CONVERT(bigint, SUBSTRING(@binId, 7, 6))) + N'.' +
CONVERT(nvarchar, CONVERT(bigint, SUBSTRING(@binId, 13, 4))) + N'/');
return @ret;
end;

通过程序也能实现,只是如果层级太深,生成的path_locator太长,总感觉不太靠谱。

下面是用Delphi实现的,Insert操作(本地E:\Doc目录下所有文件迁移到FileTable)。

procedure TForm1.BitBtn9Click(Sender: TObject);
var
lst, lstContent: TStrings;
I: Integer;
strSQL: string;
begin
lst := TStringList.Create;
lstContent := TStringList.Create;
try
GetFileStructureList('E:\Doc', lst);
strSQL := EmptyStr;
rzprogressbar1.TotalParts := lst.Count;
for I:= to lst.Count- do
begin
SplitString(lst.Strings[I], '|', lstContent);
if SameText(lstContent.Strings[], '') then //目录
strSQL := strSQL + Format('Insert into DocumentStores(name, path_locator, is_directory, is_archive) values(%S, %S, %D, %D);',
[QuotedStr(ExtractFileName(lstContent.Strings[])), QuotedStr(lstContent.Strings[]), , ]) + ##
else if SameText(lstContent.Strings[], '') then //文件
strSQL := strSQL + Format('Insert into DocumentStores(name, path_locator, file_stream) values(%S, %S, %S);',
[QuotedStr(ExtractFileName(lstContent.Strings[])), QuotedStr(lstContent.Strings[]),
StrToHex(BaseEncodeFile(lstContent.Strings[]))]) + ##;
rzprogressbar1.PartsComplete := rzprogressbar1.PartsComplete + ;
Application.ProcessMessages;
end;
try
ADOConnection1.Connected := True;
ADOConnection1.BeginTrans;
ADOQuery1.SQL.Text := strSQL;
ADOQuery1.ExecSQL;
ADOConnection1.CommitTrans;
except
ADOConnection1.RollbackTrans;
end;
finally
lst.Free;
lstContent.Free;
end;
end; //下面是公用单元
unit U_Commfunc; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, EncdDecd, Contnrs; //生成filetable用的path_locator
function GetPathLocator(root: Boolean=True): string;
function GetGUID: string;
function StrToHex(AStr: string): string;
//文件转字符串流
function BaseEncodeFile(fn: TFileName): string;
procedure SplitString(Source,Deli:string; var lst :TStrings);
//获取目录+文件的列表 返回值是文件的个数,顶层为选择的目录 为filetalbe插入用
function GetFileStructureList(Path: PChar; var lst: TStrings): LongInt; implementation function GetGUID: string;
var
LTep: TGUID;
sGUID: string;
begin
CreateGUID(LTep);
sGUID := GUIDToString(LTep);
sGUID := StringReplace(sGUID, '-', '', [rfReplaceAll]);
sGUID := Copy(sGUID, , Length(sGUID) - );
Result := sGUID;
end; function GetPathLocator(root: Boolean): string;
var
//LocatorPath的三个组成部分 S1,S2,S3;
sGuid, S1, S2, S3: string;
begin
Result := '';
if root then
Result := '/';
sGuid := GetGUID;
S1 := IntToStr(StrToInt64(StrToHex(Copy(sGuid, , ))));
S2 := IntToStr(StrToInt64(StrToHex(Copy(sGuid, , ))));
S3 := IntToStr(StrToInt64(StrToHex(Copy(sGuid, , ))));
Result := Result + S1 + '.' + S2 + '.' + S3 + '/';
end; function StrToHex(AStr: string): string;
var
i : Integer;
ch:char;
begin
Result:='0x';
for i:= to length(AStr) do
begin
ch:=AStr[i];
Result:=Result+IntToHex(Ord(ch),);
end;
end; function BaseEncodeFile(fn: TFileName): string;
var
ms: TMemoryStream;
ss: TStringStream;
str: string;
begin
ms := TMemoryStream.Create;
ss := TStringStream.Create('');
try
ms.LoadFromFile(fn);
EncdDecd.EncodeStream(ms, ss); // 将ms的内容Base64到ss中
str := ss.DataString;
str := StringReplace(str, #, '', [rfReplaceAll]); // 这里ss中数据会自动添加回车换行,所以需要将回车换行替换成空字符
str := StringReplace(str, #, '', [rfReplaceAll]);
result := str; // 返回值为Base64的Stream
finally
FreeAndNil(ms);
FreeAndNil(ss);
end;
end; procedure SplitString(Source,Deli:string; var lst :TStrings);
var
EndOfCurrentString: Integer;
begin
if lst = nil then exit;
lst.Clear;
while Pos(Deli, Source)> do
begin
EndOfCurrentString := Pos(Deli, Source);
lst.add(Copy(Source, , EndOfCurrentString - ));
Source := Copy(Source, EndOfCurrentString + length(Deli), length(Source) - EndOfCurrentString);
end;
lst.Add(source);
end; function GetFileStructureList(Path: PChar; var lst: TStrings): LongInt;
var
SearchRec: TSearchRec;
Found: Integer;
TmpStr, TmpLocator: string;
CurDir, DirLocator: PChar;
DirQue: TQueue;
C: Cardinal;
begin
Result := ;
if lst = nil then exit;
dirQue := TQueue.Create;
try
CurDir := Path;
DirLocator := PChar(GetPathLocator());
lst.Add('0|'+CurDir+'|'+DirLocator);
while CurDir <> nil do
begin
//搜索后缀,如:c:\*.*;
TmpStr := IncludeTrailingPathDelimiter(curDir)+'*.*';
Found := FindFirst(TmpStr, faAnyFile, SearchRec);
while Found = do
begin
C := GetFileAttributes(PChar(IncludeTrailingPathDelimiter(curDir) + SearchRec.Name));
//if (searchRec.Attr and faDirectory)<>0 then //这个貌似有问题/
if (C and FILE_ATTRIBUTE_DIRECTORY)<> then
begin
if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
begin
TmpStr := IncludeTrailingPathDelimiter(curDir)+SearchRec.Name;
TmpLocator := GetPathLocator(False);
TmpLocator := DirLocator + TmpLocator;
lst.Add('0|'+TmpStr+'|'+TmpLocator);
DirQue.Push(StrNew(PChar(TmpStr)));
DirQue.Push(StrNew(PChar(TmpLocator)));
end;
end else begin
Result:=Result+;
TmpLocator := GetPathLocator(False);
TmpLocator := DirLocator + TmpLocator;
lst.Add('1|'+IncludeTrailingPathDelimiter(curDir)+SearchRec.Name+'|'+TmpLocator);
end;
found:=FindNext(SearchRec);
end;
{当前目录找到后,如果队列中没有数据,则表示全部找到了;
否则就是还有子目录未查找,取一个出来继续查找。}
if DirQue.Count > then
begin
CurDir := DirQue.Pop;
DirLocator := DirQue.Pop;
end else begin
CurDir := nil;
DirLocator := nil;
end;
end;
finally
dirQue.Free;
end;
end; end.

效果图如下,目录加文件共计20个。

本地文件夹E:\Doc:

FileTable虚拟目录文件Doc:

数据库表中存放数据:

最新文章

  1. Linux命令lsb_release:查看当前系统的发行版信息
  2. paip.自适应网页设计 跟 响应式 设计的区别跟原理and实践总结
  3. Offer_answer_with_SDP_rfc3264
  4. linux 查看占用内存/CPU最多的进程
  5. Let&#39;s Encrypt这个免费的证书签发服务
  6. Java jdbc数据库连接池总结!(转)
  7. Best Time to Buy and Sell Stock III 解题思路
  8. 2的32次方 分类: C#小技巧 2014-08-05 18:18 406人阅读 评论(0) 收藏
  9. ArrayList 类和List&lt;T&gt;泛型类
  10. RabbitMQ基础
  11. Jquery判断单选框是否选中和获取选中的值
  12. Python-Django&#160;整合Django和jquery-easyui
  13. BZOJ2512 : Groc
  14. C++ 单例模式实现
  15. Graphviz的安装 - windows环境下
  16. ubuntu上第一个hello程序
  17. 一个ActiveX control的创建过程
  18. Spring boot 遇到了连接mysql的错误
  19. JUC集合之 CopyOnWriteArraySet
  20. JPA总结——实体关系映射(一对多@OneToMany)

热门文章

  1. [TimLinux] PyQt5 安装部署
  2. hdu4585Shaolin
  3. B.Box
  4. Mybatis 报错 java.lang.IllegalArgumentException: Result Maps collection does not contain value for java.lang.Inte
  5. 来看下,C# WebService WSDL自动生成代码,数组参数的BUG。。。ArrayOfString
  6. hexo + next 搭建博客时Cannot GET /tags/问题处理
  7. Java入门(一)——类、抽象类和接口
  8. 浅析堆栈段,BBS段,数据段,代码段
  9. 《Dotnet9》建站-记录建站过程中使用的一些网址
  10. 【SHOI 2007】善意的投票