Home Database Mysql Tutorial 解析SQL2005中如何使用CLR函数获取行号

解析SQL2005中如何使用CLR函数获取行号

Jun 07, 2016 pm 04:18 PM
use function how Obtain Line number parse

SQLServer数据导出到excel有很多种方法,比如dts、ssis、还可以用sql语句调用openrowset。我们这里开拓思路,用CLR来生成Excel文件,并且会考虑一些方便操作的细节。 下面我先演示一下我实现的效果,先看测试语句 -----------------------------------------

SQLServer数据导出到excel有很多种方法,比如dts、ssis、还可以用sql语句调用openrowset。我们这里开拓思路,用CLR来生成Excel文件,并且会考虑一些方便操作的细节。
下面我先演示一下我实现的效果,先看测试语句
--------------------------------------------------------------------------------

复制代码 代码如下:


exec BulkCopyToXls 'select * from testTable' , 'd:/test' , 'testTable' ,- 1
/*
开始导出数据
文件 d:/test/testTable.0.xls, 共65534条 , 大小20 ,450,868 字节
文件 d:/test/testTable.1.xls, 共65534条 , 大小 20 ,101,773 字节
文件 d:/test/testTable.2.xls, 共65534条 , 大小 20 ,040,589 字节
文件 d:/test/testTable.3.xls, 共65534条 , 大小 19 ,948,925 字节
文件 d:/test/testTable.4.xls, 共65534条 , 大小 20 ,080,974 字节
文件 d:/test/testTable.5.xls, 共65534条 , 大小 20 ,056,737 字节
文件 d:/test/testTable.6.xls, 共65534条 , 大小 20 ,590,933 字节
文件 d:/test/testTable.7.xls, 共26002条 , 大小 8,419,533 字节
导出数据完成
-------
共484740条数据,耗时 23812ms
*/


--------------------------------------------------------------------------------
上面的BulkCopyToXls存储过程是自定的CLR存储过程。他有四个参数:
第一个是sql语句用来获取数据集
第二个是文件保存的路径
第三个是结果集的名字,我们用它来给文件命名
第四个是限制单个文件可以保存多少条记录,小于等于0表示最多65534条。
前 三个参数没有什么特别,最后一个参数的设置可以让一个数据集分多个excel文件保存。比如传统excel的最大容量是65535条数据。我们这里参数设 置为-1就表示导出达到这个数字之后自动写下一个文件。如果你设置了比如100,那么每导出100条就会自动写下一个文件。
另外每个文件都可以输出字段名作为表头,所以单个文件最多容纳65534条数据。
用微软公开的biff8格式通过二进制流生成excel,服务器无需安装excel组件,,而且性能上不会比sql自带的功能差,48万多条数据,150M,用了24秒完成。

下面我们来看下CLR代码。通过sql语句获取DataReader,然后分批用biff格式来写xls文件。
--------------------------------------------------------------------------------

复制代码 代码如下:


using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
///


/// 导出数据
///

///
///
///
///
[Microsoft.SqlServer.Server.SqlProcedure ]
public static void BulkCopyToXls(SqlString sql, SqlString savePath, SqlString tableName, SqlInt32 maxRecordCount)
{
if (sql.IsNull || savePath.IsNull || tableName.IsNull)
{
SqlContext .Pipe.Send(" 输入信息不完整!" );
}
ushort _maxRecordCount = ushort .MaxValue-1;

if (maxRecordCount.IsNull == false && maxRecordCount.Value 0)
_maxRecordCount = (ushort )maxRecordCount.Value;

ExportXls(sql.Value, savePath.Value, tableName.Value, _maxRecordCount);
}

///
/// 查询数据,生成文件
///

///
///
///
///
private static void ExportXls(string sql, string savePath, string tableName, System.UInt16 maxRecordCount)
{

if (System.IO.Directory .Exists(savePath) == false )
{
System.IO.Directory .CreateDirectory(savePath);
}

using (SqlConnection conn = new SqlConnection ("context connection=true" ))
{
conn.Open();
using (SqlCommand command = conn.CreateCommand())
{
command.CommandText = sql;
using (SqlDataReader reader = command.ExecuteReader())
{
int i = 0;
int totalCount = 0;
int tick = System.Environment .TickCount;
SqlContext .Pipe.Send(" 开始导出数据" );
while (true )
{
string fileName = string .Format(@"{0}/{1}.{2}.xls" , savePath, tableName, i++);
int iExp = Write(reader, maxRecordCount, fileName);
long size = new System.IO.FileInfo (fileName).Length;
totalCount += iExp;
SqlContext .Pipe.Send(string .Format(" 文件{0}, 共{1} 条, 大小{2} 字节" , fileName, iExp, size.ToString("###,###" )));
if (iExp }
tick = System.Environment .TickCount - tick;
SqlContext .Pipe.Send(" 导出数据完成" );

SqlContext .Pipe.Send("-------" );
SqlContext .Pipe.Send(string .Format(" 共{0} 条数据,耗时{1}ms" ,totalCount,tick));
}
}
}


}
///
/// 写单元格
///

///
///
///
///
private static void WriteObject(ExcelWriter writer, object obj, System.UInt16 x, System.UInt16 y)
{
string type = obj.GetType().Name.ToString();
switch (type)
{
case "SqlBoolean" :
case "SqlByte" :
case "SqlDecimal" :
case "SqlDouble" :
case "SqlInt16" :
case "SqlInt32" :
case "SqlInt64" :
case "SqlMoney" :
case "SqlSingle" :
if (obj.ToString().ToLower() == "null" )
writer.WriteString(x, y, obj.ToString());
else
writer.WriteNumber(x, y, Convert .ToDouble(obj.ToString()));
break ;
default :
writer.WriteString(x, y, obj.ToString());
break ;
}
}
///
/// 写一批数据到一个excel 文件
///

///
///
///
///
private static int Write(SqlDataReader reader, System.UInt16 count, string fileName)
{
int iExp = count;
ExcelWriter writer = new ExcelWriter (fileName);
writer.BeginWrite();
for (System.UInt16 j = 0; j {
writer.WriteString(0, j, reader.GetName(j));
}
for (System.UInt16 i = 1; i {
if (reader.Read() == false )
{
iExp = i-1;
break ;
}
for (System.UInt16 j = 0; j {
WriteObject(writer, reader.GetSqlValue(j), i, j);
}
}
writer.EndWrite();
return iExp;
}

///
/// 写excel 的对象
///

public class ExcelWriter
{
System.IO.FileStream _wirter;
public ExcelWriter(string strPath)
{
_wirter = new System.IO.FileStream (strPath, System.IO.FileMode .OpenOrCreate);
}
///
/// 写入short 数组
///

///
private void _writeFile(System.UInt16 [] values)
{
foreach (System.UInt16 v in values)
{
byte [] b = System.BitConverter .GetBytes(v);
_wirter.Write(b, 0, b.Length);
}
}
///
/// 写文件头
///

public void BeginWrite()
{
_writeFile(new System.UInt16 [] { 0x809, 8, 0, 0x10, 0, 0 });
}
///
/// 写文件尾
///

public void EndWrite()
{
_writeFile(new System.UInt16 [] { 0xa, 0 });
_wirter.Close();
}
///
/// 写一个数字到单元格x,y
///

///
///
///
public void WriteNumber(System.UInt16 x, System.UInt16 y, double value)
{
_writeFile(new System.UInt16 [] { 0x203, 14, x, y, 0 });
byte [] b = System.BitConverter .GetBytes(value);
_wirter.Write(b, 0, b.Length);
}
///
/// 写一个字符到单元格x,y
///

///
///
///
public void WriteString(System.UInt16 x, System.UInt16 y, string value)
{
byte [] b = System.Text.Encoding .Default.GetBytes(value);
_writeFile(new System.UInt16 [] { 0x204, (System.UInt16 )(b.Length + 8), x, y, 0, (System.UInt16 )b.Length });
_wirter.Write(b, 0, b.Length);
}
}
};


把上面代码编译为TestExcel.dll,copy到服务器目录。然后通过如下SQL语句部署存储过程。
--------------------------------------------------------------------------------

复制代码 代码如下:

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Roblox: Bubble Gum Simulator Infinity - How To Get And Use Royal Keys
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Fusion System, Explained
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers Of The Witch Tree - How To Unlock The Grappling Hook
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1670
14
PHP Tutorial
1274
29
C# Tutorial
1256
24
BTCC tutorial: How to bind and use MetaMask wallet on BTCC exchange? BTCC tutorial: How to bind and use MetaMask wallet on BTCC exchange? Apr 26, 2024 am 09:40 AM

MetaMask (also called Little Fox Wallet in Chinese) is a free and well-received encryption wallet software. Currently, BTCC supports binding to the MetaMask wallet. After binding, you can use the MetaMask wallet to quickly log in, store value, buy coins, etc., and you can also get 20 USDT trial bonus for the first time binding. In the BTCCMetaMask wallet tutorial, we will introduce in detail how to register and use MetaMask, and how to bind and use the Little Fox wallet in BTCC. What is MetaMask wallet? With over 30 million users, MetaMask Little Fox Wallet is one of the most popular cryptocurrency wallets today. It is free to use and can be installed on the network as an extension

Tips for dynamically creating new functions in golang functions Tips for dynamically creating new functions in golang functions Apr 25, 2024 pm 02:39 PM

Go language provides two dynamic function creation technologies: closure and reflection. closures allow access to variables within the closure scope, and reflection can create new functions using the FuncOf function. These technologies are useful in customizing HTTP routers, implementing highly customizable systems, and building pluggable components.

Considerations for parameter order in C++ function naming Considerations for parameter order in C++ function naming Apr 24, 2024 pm 04:21 PM

In C++ function naming, it is crucial to consider parameter order to improve readability, reduce errors, and facilitate refactoring. Common parameter order conventions include: action-object, object-action, semantic meaning, and standard library compliance. The optimal order depends on the purpose of the function, parameter types, potential confusion, and language conventions.

Complete collection of excel function formulas Complete collection of excel function formulas May 07, 2024 pm 12:04 PM

1. The SUM function is used to sum the numbers in a column or a group of cells, for example: =SUM(A1:J10). 2. The AVERAGE function is used to calculate the average of the numbers in a column or a group of cells, for example: =AVERAGE(A1:A10). 3. COUNT function, used to count the number of numbers or text in a column or a group of cells, for example: =COUNT(A1:A10) 4. IF function, used to make logical judgments based on specified conditions and return the corresponding result.

Comparison of the advantages and disadvantages of C++ function default parameters and variable parameters Comparison of the advantages and disadvantages of C++ function default parameters and variable parameters Apr 21, 2024 am 10:21 AM

The advantages of default parameters in C++ functions include simplifying calls, enhancing readability, and avoiding errors. The disadvantages are limited flexibility and naming restrictions. Advantages of variadic parameters include unlimited flexibility and dynamic binding. Disadvantages include greater complexity, implicit type conversions, and difficulty in debugging.

What are the benefits of C++ functions returning reference types? What are the benefits of C++ functions returning reference types? Apr 20, 2024 pm 09:12 PM

The benefits of functions returning reference types in C++ include: Performance improvements: Passing by reference avoids object copying, thus saving memory and time. Direct modification: The caller can directly modify the returned reference object without reassigning it. Code simplicity: Passing by reference simplifies the code and requires no additional assignment operations.

How to write efficient and maintainable functions in Java? How to write efficient and maintainable functions in Java? Apr 24, 2024 am 11:33 AM

The key to writing efficient and maintainable Java functions is: keep it simple. Use meaningful naming. Handle special situations. Use appropriate visibility.

C++ Function Exception Advanced: Customized Error Handling C++ Function Exception Advanced: Customized Error Handling May 01, 2024 pm 06:39 PM

Exception handling in C++ can be enhanced through custom exception classes that provide specific error messages, contextual information, and perform custom actions based on the error type. Define an exception class inherited from std::exception to provide specific error information. Use the throw keyword to throw a custom exception. Use dynamic_cast in a try-catch block to convert the caught exception to a custom exception type. In the actual case, the open_file function throws a FileNotFoundException exception. Catching and handling the exception can provide a more specific error message.

See all articles