PCB MS SQL 标量函数与表值函数(CLR) 实现文件与目录操作
一.C#写SQL SERVER(CLR)实现文件操作
标量函数: 文件移动 ,复制,检测文件存在,写入新文件文本,读取文本,创建目录,删除目录,检测目录是否存在
/// <summary>
/// 将现有文件复制到新文件。允许覆盖同名的文件。
/// </summary>
/// <param name="sourceFileName">要复制的文件</param>
/// <param name="destFileName">目标文件的名称。不能是目录。</param>
/// <param name="overwrite">如果可以覆盖目标文件,则为 true;否则为 false。</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlBoolean FileCopy (string sourceFileName, string destFileName, bool overwrite) {
try { File.Copy (sourceFileName, destFileName, overwrite);
return File.Exists (destFileName);
} catch (Exception) {
return false;
}
return false;
}
/// <summary>
/// 将指定文件移到新位置,并提供指定新文件名的选项。
/// </summary>
/// <param name="sourceFileName">要复制的文件</param>
/// <param name="destFileName">目标文件的名称。不能是目录。</param>
/// <param name="overwrite">如果可以覆盖目标文件,则为 true;否则为 false。</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlBoolean FileMove (string sourceFileName, string destFileName, bool overwrite) {
try {
bool isExists = File.Exists (destFileName);
if (isExists && overwrite)
File.Delete (destFileName);
if (isExists && !overwrite)
return false;
File.Move (sourceFileName, destFileName);
return File.Exists (destFileName);
} catch (Exception) {
return false;
}
return false;
}
/// <summary>
/// 确定指定的文件是否存在。
/// </summary>
/// <param name="FilePath">文件路径</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlBoolean FileExists (string FilePath) {
try { return File.Exists (FilePath);
} catch (Exception) {
return false;
}
return false;
}
/// <summary>
/// 创建一个新文件,在其中写入指定的字符串,然后关闭文件。如果目标文件已存在,则覆盖该文件。
/// </summary>
/// <param name="FilePath">文件路径</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static bool FileWriteText (string FilePath, string Contents) {
try {
File.WriteAllText (FilePath, Contents);
return File.Exists (FilePath);
} catch (Exception) {
return false;
}
return false;
}
/// <summary>
/// 读取文本
/// </summary>
/// <param name="FilePath">文件路径</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static string FileReadText (string FilePath) {
try {
return File.ReadAllText (FilePath);
} catch (Exception) {
return "";
}
return "";
}
/// <summary>
/// 创建目录
/// </summary>
/// <param name="FilePath">文件路径</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static bool DirectoryCreateDirectory (string DirPath) {
try {
Directory.CreateDirectory (DirPath);
return Directory.Exists (DirPath);
} catch (Exception) {
return false;
}
return false;
}
/// <summary>
/// 删除目录
/// </summary>
/// <param name="FilePath">文件路径</param>
/// <param name="recursive">是否删除所有子目录与文件</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static bool DirectoryDelete (string DirPath, bool recursive) {
try {
Directory.Delete (DirPath, recursive);
return !Directory.Exists (DirPath);
} catch (Exception) {
return false;
}
return false;
}
/// <summary>
/// 目录是否存在
/// </summary>
/// <param name="FilePath">文件路径</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static bool DirectoryExists (string DirPath) {
try {
return Directory.Exists (DirPath);
} catch (Exception) {
return false;
}
return false;
}
表值函数:读取文本,获取文件信息,获取子目录清单
/// <summary>
/// 表值函数
///--属性 --说明
///--DataAccess --指示该函数是否涉及访问存储在SQL Server的数据
///--FillRowMethodName --在同一个类的方法的名称作为表值函数(TVF),这个参数在表值函数中才会用到,用于指定表值函数的数据填充方法
///--IsDeterministic --指示用户定义的函数是否是确定性的
///--IsPrecise --指示函数是否涉及不精确计算,如浮点运算
///--Name --函数在SQL Server中注册时使用的函数的名称
///--SystemDataAccess --指示该函数是否需要访问存储在系统目录或SQL Server虚拟系统表中的数据
///--TableDefinition --如果方法作为表值函数(TVF),则为一个字符串,该字符串表示表结构的定义
/// </summary>
public partial class SQLfunction
{
/// <summary>
/// SQL Server 读取文本转为表
/// </summary>
/// <param name="separator"></param>
/// <param name="pendingString"></param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction(
DataAccess = DataAccessKind.Read,
IsDeterministic = true,
Name = "FileReadText2Table",
FillRowMethodName = "SqlSplit_FillRow",
TableDefinition = "SerialNumber int,StringValue nvarchar(1024)")]
public static IEnumerable FileReadText2Table(string path)
{
string[] strs = { };
strs = File.ReadAllLines(path);
List<ResultData> resultDataList = new List<ResultData>();
for (int i = ; i < strs.Length; i++)
{
resultDataList.Add(new ResultData(i + , strs[i]));
}
return resultDataList;
} /// <summary>
/// SQL Server 文件信息获取
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction(
DataAccess = DataAccessKind.Read,
IsDeterministic = true,
Name = "FileInfo2Table",
FillRowMethodName = "SqlKeyValue_FillRow",
TableDefinition = "SerialNumber int,StringKey nvarchar(1024),StringValue nvarchar(1024)")]
public static IEnumerable FileInfo2Table(string path)
{
List<ResultKeyValueData> resultDataList = new List<ResultKeyValueData>();
FileInfo fileInfo = new FileInfo(path);
resultDataList.Add(new ResultKeyValueData(, "FullName", fileInfo.FullName));
resultDataList.Add(new ResultKeyValueData(, "DirectoryName", fileInfo.DirectoryName));
resultDataList.Add(new ResultKeyValueData(, "Name", Path.GetFileNameWithoutExtension(fileInfo.FullName)));
resultDataList.Add(new ResultKeyValueData(, "Extension", fileInfo.Extension));
resultDataList.Add(new ResultKeyValueData(, "IsReadOnly", fileInfo.IsReadOnly.ToString()));
resultDataList.Add(new ResultKeyValueData(, "CreationTime", fileInfo.CreationTime.ToString()));
resultDataList.Add(new ResultKeyValueData(, "LastAccessTime", fileInfo.LastAccessTime.ToString()));
resultDataList.Add(new ResultKeyValueData(, "LastWriteTime", fileInfo.LastWriteTime.ToString()));
resultDataList.Add(new ResultKeyValueData(, "Length", fileInfo.Length.ToString()));
resultDataList.Add(new ResultKeyValueData(, "Attributes", fileInfo.Attributes.ToString()));
return resultDataList;
} /// <summary>
/// SQL Server 获取目录--子目录清单
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction(
DataAccess = DataAccessKind.Read,
IsDeterministic = true,
Name = "DirectoryGetFiles",
FillRowMethodName = "SqlSplit_FillRow",
TableDefinition = "SerialNumber int,StringValue nvarchar(1024)")]
public static IEnumerable DirectoryGetFiles(string path)
{
string[] strs = { };
strs = Directory.GetFiles(path);
List<ResultData> resultDataList = new List<ResultData>();
for (int i = ; i < strs.Length; i++)
{
resultDataList.Add(new ResultData(i + , strs[i]));
}
return resultDataList;
} /// <summary>
/// SQL Server 获取目录--文件清单
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction(
DataAccess = DataAccessKind.Read,
IsDeterministic = true,
Name = "DirectoryGetDirectories",
FillRowMethodName = "SqlSplit_FillRow",
TableDefinition = "SerialNumber int,StringValue nvarchar(1024)")]
public static IEnumerable DirectoryGetDirectories(string path)
{
string[] strs = { };
IntPtr admin_token = IntPtr.Zero;
if (WinLogonHelper.LogonUser(ref admin_token) != )
{
using (WindowsIdentity wid_admin = new WindowsIdentity(admin_token))
{
using (WindowsImpersonationContext wic = wid_admin.Impersonate())
{
strs = Directory.GetDirectories(path);
}
}
}
List<ResultData> resultDataList = new List<ResultData>();
for (int i = ; i < strs.Length; i++)
{
resultDataList.Add(new ResultData(i + , strs[i]));
}
return resultDataList;
} } /// <summary>
/// 表值函数
///--属性 --说明
///--DataAccess --指示该函数是否涉及访问存储在SQL Server的数据
///--FillRowMethodName --在同一个类的方法的名称作为表值函数(TVF),这个参数在表值函数中才会用到,用于指定表值函数的数据填充方法
///--IsDeterministic --指示用户定义的函数是否是确定性的
///--IsPrecise --指示函数是否涉及不精确计算,如浮点运算
///--Name --函数在SQL Server中注册时使用的函数的名称
///--SystemDataAccess --指示该函数是否需要访问存储在系统目录或SQL Server虚拟系统表中的数据
///--TableDefinition --如果方法作为表值函数(TVF),则为一个字符串,该字符串表示表结构的定义
/// </summary>
public partial class SQLfunction
{
/// <summary>
/// SQL Server 字符串分割方法
/// </summary>
/// <param name="separator"></param>
/// <param name="pendingString"></param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction(
DataAccess = DataAccessKind.Read,
IsDeterministic = true,
Name = "SqlSplit",
FillRowMethodName = "SqlSplit_FillRow",
TableDefinition = "SerialNumber int,StringValue nvarchar(1024)")]
public static IEnumerable SqlSplit(SqlString separator, SqlString pendingString)
{
string _separator = string.Empty;
string _pendingString = string.Empty;
if (pendingString.IsNull) return null;
_pendingString = pendingString.ToString();
if (string.IsNullOrEmpty(_pendingString)) return null;
_separator = separator.IsNull ? "," : separator.ToString();
_separator = string.IsNullOrEmpty(_separator) ? "," : _separator;
string[] strs = _pendingString.Split(new string[] { _separator }, StringSplitOptions.RemoveEmptyEntries);
List<ResultData> resultDataList = new List<ResultData>();
for (int i = ; i < strs.Length; i++)
{
resultDataList.Add(new ResultData(i + , strs[i]));
}
return resultDataList;
} #region 表值变量 Id,Value
/// <summary>
/// 填充数据方法
/// </summary>
/// <param name="obj"></param>
/// <param name="serialNumber"></param>
/// <param name="stringValue"></param>
public static void SqlSplit_FillRow(Object obj, out SqlInt32 SerialNumber, out SqlString StringValue)
{
ResultData resultData = (ResultData)obj;
SerialNumber = resultData.SerialNumber;
StringValue = resultData.StringValue;
} /// <summary>
/// 定义返回类型
/// </summary>
public class ResultData
{
/// <summary>
/// 序号,即行号
/// </summary>
public SqlInt32 SerialNumber { get; set; } /// <summary>
/// 分割后的每个子字符串
/// </summary>
public SqlString StringValue { get; set; } public ResultData(SqlInt32 serialNumber, SqlString stringValue)
{
SerialNumber = serialNumber;
StringValue = stringValue;
}
} #endregion #region 表值变量 ID,Key,Value
/// <summary>
/// 填充数据方法
/// </summary>
/// <param name="obj"></param>
/// <param name="serialNumber"></param>
/// <param name="stringValue"></param>
public static void SqlKeyValue_FillRow(Object obj, out SqlInt32 SerialNumber, out SqlString StringKey, out SqlString StringValue)
{
ResultKeyValueData resultData = (ResultKeyValueData)obj;
SerialNumber = resultData.SerialNumber;
StringKey = resultData.StringKey;
StringValue = resultData.StringValue;
} /// <summary>
/// 定义返回类型
/// </summary>
public class ResultKeyValueData
{
/// <summary>
/// 序号,即行号
/// </summary>
public SqlInt32 SerialNumber { get; set; }
/// <summary>
/// 键
/// </summary>
public SqlString StringKey { get; set; }
/// <summary>
/// 值
/// </summary>
public SqlString StringValue { get; set; } public ResultKeyValueData(SqlInt32 serialNumber, SqlString stringKey, SqlString stringValue)
{
SerialNumber = serialNumber;
StringKey = stringKey;
StringValue = stringValue;
}
} #endregion }
二.SQL服务器CLR配置(允许SQL调用.net程序)
sp_configure 'show advanced options', 1;
RECONFIGURE WITH override
GO
sp_configure 'clr enabled', 1;
RECONFIGURE WITH override
GO
Sp_changedbowner 'sa',true --sa改为当前登入用户名
alter database [dbname] set trustworthy on --bbname 改为自己的库名
三.注册 CLR 程序集
create ASSEMBLY SQLfunctionAssembly
FROM 'D:\SQLClr.dll' --改为自己C#写的dll路径填写
WITH PERMISSION_SET = UNSAFE;
创建的.net程序集数据会写入下表:
select * from sys.assemblies
select * from sys.assembly_files
四.创建标量函数与表值函数(分别2类函数举例)
1.标量函数----文件复制
CREATE FUNCTION [dbo].[FileCopy](@sourceFileName [nvarchar](max), @destFileName [nvarchar](max), @overwrite [bit])
RETURNS [bit] WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [SQLfunctionAssembly].[SQLClr.SQLfunction].[FileCopy]
2.表值函数----获取文件信息
CREATE FUNCTION [dbo].[FileInfo2Table](@path [nvarchar](max))
RETURNS TABLE (
[SerialNumber] [int] NULL,
[StringKey] [nvarchar](max) NULL,
[StringValue] [nvarchar](max) NULL
) WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [SQLfunctionAssembly].[SQLClr.SQLfunction].[FileInfo2Table]
五.测试文件操作函数
测试3个函数
说明一下:D:\features文件是指服务器上的D盘features文件,而不是客户端的文件哦.
DECLARE @file VARCHAR(MAX)
SET @file = 'D:\features'
--1.读取文件属性到Table
select * from dbo.FileInfo2Table(@file)
--2.读取文本到Table
select * from dbo.FileReadText2Table(@file)
-- 3.读取文本
select dbo.FileReadText(@file)
测试结果:
六.SQL SERVER访问共享目录方法
采用SQL SERVER操作文件是不允许操作局域网中的共享文件的,若想实现的话需Windows模拟域帐号登入,另一篇文章有讲到的。PCB 工程系统 模拟windows域帐号登入
以文件复制为例代码如下:
/// <summary>
/// 读取文本
/// </summary>
/// <param name="FilePath">文件路径</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static string FileReadText (string FilePath) {
try {
IntPtr admin_token = IntPtr.Zero;
if (WinLogonHelper.LogonUser (ref admin_token) != ) {
using (WindowsIdentity wid_admin = new WindowsIdentity (admin_token)) {
using (WindowsImpersonationContext wic = wid_admin.Impersonate ()) {
return File.ReadAllText (FilePath);
}
}
}
} catch (Exception) {
return "";
}
return "";
} public class WinLogonHelper {
/// <summary>
/// 模拟windows登录域
/// </summary>
[DllImport ("advapi32.DLL", SetLastError = true)]
public static extern int LogonUser (string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
public static int LogonUser (ref IntPtr phToken) {
return WinLogonHelper.LogonUser ("用户名", "域名", "密码", , , ref phToken);
}
}
PCB MS SQL 标量函数与表值函数(CLR) 实现文件与目录操作的更多相关文章
- PCB MS SQL 标量函数(CLR) 实现DataTable转HTML的方法
一.准备需转为HMLT字符串的DataTable数据 在数据库中执行一段SQL返回的数据 需转换后的HTML的文本 <html ><head></head>< ...
- PCB MS SQL 标量函数(CLR) 实现Socket发送消息
在PCB业务系统中,数据库中的数据总是被应用端主动连接数据库并操作数据,是否想过可以让数据库主动的将数据推送出去呢! 答应其实是可以的.比如有这样的应用场景! 当SQL SERVER数据库满足某个条件 ...
- PCB MS SQL 标量函数(CLR) 实现DataTable转Json方法
一.准备需转为json字符串的DataTable数据 在数据库中执行一段SQL返回的数据 需转换后的JSON字符串的效果 [{"TechName":"开料",& ...
- PCB MS SQL表值函数与CLR 表值函数 (例:字符串分割转表)
将字符串分割为表表经常用到,这里 SQL表值函数与CLR 表值函数,两种实现方法例出来如下: SELECT * FROM FP_EMSDB_PUB.dbo.SqlSplit('/','1oz/1.5 ...
- 转载——CLR标量函数、表值函数和聚合函数(UDA)
本节主要介绍使用CLR创建标量函数,表值函数和聚合函数. 所谓标量函数指的就是此函数只返回一个值.表值函数返回值是一个表.聚合函数是在select语句中使用的,用来聚合一个结果集,类似于Sum()或是 ...
- MS SQL Server2012中的EOMONTH函数
MS SQL Server2012中的EOMONTH函数 这个函数是获取一个指定日期所在月份最后一天的日期.可以得到某一个月月份的最后一天 如: declare @orderdate date=' ...
- sqlserver自定义函数(标量值函数,表值函数)
用户自定义的函数有两类:表值函数.标量值函数. 表值函数:返回值是数据表的函数 调用方式 select b.* from tableA a accross apply Fun_BiaoZhiFun ...
- 关于T-SQL重编译那点事,内联函数和表值函数在编译生成执行计划的区别
本文出处:http://www.cnblogs.com/wy123/p/6266724.html 最近在学习 WITH RECOMPILE和OPTION(RECOMPILE)在重编译上的区别的时候,无 ...
- PCB MS SQL 排序应用---SQL相邻数据区间值求解
其中一篇 博文中有写<PCB MS SQL 排序应用---相邻数据且相同合并处理>此篇有也应相用也同的技巧,实现相邻数据区间值求解 示例: 原数据:处理前 求出区间值:处理后 SQL 代码 ...
随机推荐
- 社交网络图中结点的“重要性”计算 (30 分) C++解法
社交网络图中结点的"重要性"计算 (30 分) 在社交网络中,个人或单位(结点)之间通过某些关系(边)联系起来.他们受到这些关系的影响,这种影响可以理解为网络中相互连接的结点之间蔓 ...
- SIGFPE能处理上下溢吗?
SIGFPE可以报告算术异常.包括上下溢.除零等. C标准库说: 各种实现报告的异常类型区别也很大,但几乎没有实现会报告整型溢出. 真的吗?我测试了一下,发现在GCC上,整型.浮点上下溢都不会报告,但 ...
- 框架学习八:二维码(Zxing)
本文转自夏神:http://blog.csdn.net/xiaanming/article/details/10163203 一.用什么 二维码扫描用的google的开源框架Zxing. 二.下载 地 ...
- enote笔记语言(2)(ver0.5)
why not(whyn't) 为什么不(与“why”相反对应,是它的反面.它的矛盾对立面) how对策 how设计 key-memo: ...
- JavaScript Simple Explain and Use
Javascript 说明: JavaScript 和 Java 之间几乎没有任何关系. JavaScript原名为LiveScript,他的作用只是为了处理一些复杂的动态网页. 目前,JS是遵循EC ...
- Java中对象流使用的一个注意事项
再写jsp的实验作业的时候,需要用到java中对象流,但是碰到了之前没有遇到过的情况,改bug改到崩溃!!记录下来供大家分享 如果要用对象流去读取一个文件,一定要先判断这个文件的内容是否为空,如果为空 ...
- js中复制功能总结
目前copy主流有四种方式:ZeroClipboard,Clipboard.js,execCommand,setData,clipboardData 概况: ZeroClipboard 就是常说的Fl ...
- Spring MVC学习总结(13)——Spring MVC集成Swagger时文档无法排序问题
添加排序属性: window.swaggerUi = new SwaggerUi({ ... apisSorter: "alpha", // can also ...
- 控制公司(codevs 2051)
题目描述 Description 有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分.例如,福特公司拥有马自达公司12%的股票.据说,如果至少满足了以下三个条件之一,公司A就可以 ...
- 另一套备用的代码,通过service调用和登陆用户交互
结合这两个东东,应该差不多可以搞定我需要的事情啦. 因为更改不了service代码,所以希望从service调用的代码里,争脱出来,和本地登陆用户进行交互启动. #include <window ...