C # 프로그램 내에서 대량의 SQL 문 (테이블, 뷰 및 저장 프로 시저 생성)을 실행해야합니다.
이러한 문은 문으로 구분해야 GO
하지만 문을 SqlCommand.ExecuteNonQuery()
좋아하지 않습니다 GO
. 참조 용으로 게시 할 것이라고 생각하는 내 솔루션은 SQL 문자열을 GO
줄로 분할하고 각 배치를 개별적으로 실행 하는 것이 었습니다 .
더 쉽고 더 나은 방법이 있습니까?
답변
GO 구분 기호를 이해하는 SQL Server 관리 개체 (SMO)를 사용합니다. 여기 내 블로그 게시물을 참조하십시오 : http://weblogs.asp.net/jongalloway/Handling-_2200_GO_2200_-Separators-in-SQL-Scripts- 2D00 -the-easy-way
샘플 코드 :
public static void Main()
{
string scriptDirectory = "c:\\temp\\sqltest\\";
string sqlConnectionString = "Integrated Security=SSPI;" +
"Persist Security Info=True;Initial Catalog=Northwind;Data Source=(local)";
DirectoryInfo di = new DirectoryInfo(scriptDirectory);
FileInfo[] rgFiles = di.GetFiles("*.sql");
foreach (FileInfo fi in rgFiles)
{
FileInfo fileInfo = new FileInfo(fi.FullName);
string script = fileInfo.OpenText().ReadToEnd();
using (SqlConnection connection = new SqlConnection(sqlConnectionString))
{
Server server = new Server(new ServerConnection(connection));
server.ConnectionContext.ExecuteNonQuery(script);
}
}
}
이것이 작동하지 않으면 Phil Haack의 라이브러리를 참조하십시오. http://haacked.com/archive/2007/11/04/a-library-for-executing-sql-scripts-with-go-separators -and.aspx
답변
이것이 바로 내 당면한 문제를 해결하기 위해 함께 두드린 것입니다.
private void ExecuteBatchNonQuery(string sql, SqlConnection conn) {
string sqlBatch = string.Empty;
SqlCommand cmd = new SqlCommand(string.Empty, conn);
conn.Open();
sql += "\nGO"; // make sure last batch is executed.
try {
foreach (string line in sql.Split(new string[2] { "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries)) {
if (line.ToUpperInvariant().Trim() == "GO") {
cmd.CommandText = sqlBatch;
cmd.ExecuteNonQuery();
sqlBatch = string.Empty;
} else {
sqlBatch += line + "\n";
}
}
} finally {
conn.Close();
}
}
GO 명령이 자체 라인에 있어야하며 블록 주석을 감지하지 않으므로 이런 종류의 것이 분할되어 오류가 발생합니다.
ExecuteBatchNonQuery(@"
/*
GO
*/", conn);
답변
SQL 관리 개체 를 사용하여이를 수행 할 수 있습니다 . 이는 Management Studio가 쿼리를 실행하는 데 사용하는 것과 동일한 개체입니다. 나는 Server.ConnectionContext.ExecuteNonQuery()
당신이 필요한 것을 수행 할 것이라고 믿습니다 .
답변
“GO”일괄 구분 키워드는 실제로 SQL Management Studio 자체에서 사용되므로 서버로 보내는 일괄 처리를 종료 할 위치를 알고 SQL 서버로 전달되지 않습니다. 원하는 경우 Management Studio에서 키워드를 변경할 수도 있습니다.
답변
나는로 결정 끝에 몇 번 이것 좀 봐 EF 구현
A를 위해 수정 비트SqlConnection
public static void ExecuteSqlScript(this SqlConnection sqlConnection, string sqlBatch)
{
// Handle backslash utility statement (see http://technet.microsoft.com/en-us/library/dd207007.aspx)
sqlBatch = Regex.Replace(sqlBatch, @"\\(\r\n|\r|\n)", string.Empty);
// Handle batch splitting utility statement (see http://technet.microsoft.com/en-us/library/ms188037.aspx)
var batches = Regex.Split(
sqlBatch,
string.Format(CultureInfo.InvariantCulture, @"^\s*({0}[ \t]+[0-9]+|{0})(?:\s+|$)", BatchTerminator),
RegexOptions.IgnoreCase | RegexOptions.Multiline);
for (int i = 0; i < batches.Length; ++i)
{
// Skip batches that merely contain the batch terminator
if (batches[i].StartsWith(BatchTerminator, StringComparison.OrdinalIgnoreCase) ||
(i == batches.Length - 1 && string.IsNullOrWhiteSpace(batches[i])))
{
continue;
}
// Include batch terminator if the next element is a batch terminator
if (batches.Length > i + 1 &&
batches[i + 1].StartsWith(BatchTerminator, StringComparison.OrdinalIgnoreCase))
{
int repeatCount = 1;
// Handle count parameter on the batch splitting utility statement
if (!string.Equals(batches[i + 1], BatchTerminator, StringComparison.OrdinalIgnoreCase))
{
repeatCount = int.Parse(Regex.Match(batches[i + 1], @"([0-9]+)").Value, CultureInfo.InvariantCulture);
}
for (int j = 0; j < repeatCount; ++j)
{
var command = sqlConnection.CreateCommand();
command.CommandText = batches[i];
command.ExecuteNonQuery();
}
}
else
{
var command = sqlConnection.CreateCommand();
command.CommandText = batches[i];
command.ExecuteNonQuery();
}
}
}
답변
SMO 개체를 설치하지 않으려면 gplex 도구를 사용할 수 있습니다 ( 이 답변 참조 )
답변
Blorgbeard의 솔루션을 기반으로합니다.
foreach (var sqlBatch in commandText.Split(new[] { "GO" }, StringSplitOptions.RemoveEmptyEntries))
{
sqlCommand.CommandText = sqlBatch;
sqlCommand.ExecuteNonQuery();
}