尝试创建一个将sql表写入文件管道分隔的clr。
尚未测试输出,因此不确定它是否正在尝试创建连接字符串。我希望它是动态的,因此它可以根据正在执行的sql server来计算连接字符串。
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Security;
using System.Security.Principal;
using Microsoft.SqlServer.Server;
public partial class CLR_uspExportToFiles
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void uspExportToFiles(string TableOrQuery, string Delimiter, int Debug, string FilePath, string Filename)
{
var output = FilePath + Filename;
using (System.IO.StreamWriter file = new System.IO.StreamWriter(output))
{
const string DATASOURCE = "Data Source=";
const string INITIALCATALOG = ";Initial Catalog=";
const string INTEGRATEDSECURITY = ";Integrated Security=True;Enlist=false;";
string ConnString;
string InstanceName;
string DbName;
//Establish a connection in the current context to dynamically get the current
//Server and Database Name.
using (SqlConnection sysconn = new SqlConnection("context connection=true"))
{
SqlCommand GetSQLSystemProperties = new SqlCommand();
GetSQLSystemProperties.Connection = sysconn;
sysconn.Open();
//Get the current SQL Server instance name
GetSQLSystemProperties.CommandText = "SELECT @@Servername";
InstanceName = (string)GetSQLSystemProperties.ExecuteScalar();
//Get the current Database Name
GetSQLSystemProperties.CommandText = "SELECT DB_NAME()";
DbName = (string)GetSQLSystemProperties.ExecuteScalar();
sysconn.Close();
//Dynamically construct the connection string to establish a connection outside
//of the current context, so that any error written to the error table won't be
//rolled back.
ConnString = DATASOURCE + InstanceName + INITIALCATALOG + DbName + INTEGRATEDSECURITY;
using (SqlConnection conn = new SqlConnection(ConnString))
{
using (SqlCommand cmd = new SqlCommand("SELECT * FROM @TableOrQuery", conn))
{
//cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TableOrQuery", TableOrQuery);
//cmd.Parameters.AddWithValue("@Del", Delimiter);
//cmd.Parameters.AddWithValue("@Debug", Debug);
//cmd.Parameters.AddWithValue("@FilePath", FilePath);
//cmd.Parameters.AddWithValue("@Filename", Filename);
using (SqlDataAdapter sda = new SqlDataAdapter())
{
sda.SelectCommand = cmd;
using (DataTable dt = new DataTable())
{
sda.Fill(dt);
//Build the Text file data.
string txt = string.Empty;
foreach (DataColumn column in dt.Columns)
{
//Add the Header row for Text file.
txt += column.ColumnName + "|";
}
//Add new line.
txt += "\r\n";
file.WriteLine(txt);
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn column in dt.Columns)
{
//Add the Data rows.
txt += row[column.ColumnName].ToString() + "|";
}
//Add new line.
txt += "\r\n";
file.WriteLine(txt);
}
}
}
};
}
}
}
}
}
获取错误
Msg 6522, Level 16, State 1, Procedure CLR_uspExportToFiles, Line 0
A .NET Framework error occurred during execution of user-defined routine or aggregate "CLR_uspExportToFiles":
System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)
System.Data.SqlClient.SqlException:
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, Boolean withFailover, SqlAuthenticationMethod authType)
at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover)
at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout)
at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance)
at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePa...
并且不确定如何修复
答案 0 :(得分:1)
一些注意事项:
Sql***
类型而不是本机.NET类型。含义,SqlString
(或有时SqlChars
)代替string
,SqlInt32
而非int
等。请参阅Mapping CLR Parameter Data了解完整列表SELECT @@SERVERNAME
和SELECT DB_NAME()
),因为您不需要第二个外部连接。@@SERVERNAME
即可。您可以通过SqlConnection
属性从Database
获取数据库名称。是的,当使用Context Connection
时,它将被设置为当前数据库(该查询的当前数据库)。Parameters.AddWithValue
。单独创建参数并指定SqlDbType
和最大长度。DataTable
除非您绝对肯定传入的任何表永远不会那么大(就数据/已用空间而言,而不是索引) 。 Fill
方法将整个结果集吸入内存(即DataTable
)。那是相当危险的。您应该使用SqlDataReader
并将结果集的每一行写入文件,因为它是从SqlDataReader
读取的。txt
变量。您可以在通过Write方法阅读时写出每个字段。\r\n
),因为WriteLine
处理了换行符。方法(同样适用于Console.Write
vs Console.WriteLine
)。通过同时使用WriteLine
和附加\r\n
,每一行数据都会以空行分隔。有关使用SQLCLR的更多信息,请参阅我在SQL Sever Central上编写的系列:Stairway to SQLCLR(需要免费注册)。
此外,我编写了一个SQLCLR存储过程来完成此操作(将查询的结果集转储到文件中)作为SQL#库的一部分。请注意,虽然有免费版本的SQL#,但 DB_BulkExport 存储过程仅在完整版中可用。