programing

트랜잭션 내에서 "GO" 사용

codeshow 2023. 7. 31. 21:59
반응형

트랜잭션 내에서 "GO" 사용

App_Start에서 데이터베이스 설치/업그레이드를 시도하는 웹 앱을 구축하고 있습니다.설치 절차의 일부는 데이터베이스에 asp.net 기능이 설치되어 있는지 확인하는 것입니다.이를 위해 시스템을 사용합니다.웹.관리.SqlServices 개체입니다.

SQL 트랜잭션 내에서 모든 데이터베이스 작업을 수행하고, 트랜잭션 중 하나라도 실패하면 트랜잭션을 롤백하고 데이터베이스를 그대로 유지합니다.

SqlServices 개체에 트랜잭션이 아닌 ConnectionString을 사용하는 "설치" 메서드가 있습니다.대신 SQL 서비스를 사용합니다.다음과 같은 Application Services 스크립트 생성:

string script = SqlServices.GenerateApplicationServicesScripts(true, SqlFeatures.All, _connection.Database);
SqlHelper.ExecuteNonQuery(transaction, CommandType.Text, script, ...);

그런 다음 Enterprise Library의 SqlHelper를 사용합니다.

그러나 이 경우 예외가 발생하고 오류가 발생합니다. 몇 가지는 아래와 같습니다.

Incorrect syntax near 'GO'.
Incorrect syntax near 'GO'.
Incorrect syntax near 'GO'.
Incorrect syntax near 'GO'.
Incorrect syntax near the keyword 'USE'.
Incorrect syntax near the keyword 'CREATE'.
Incorrect syntax near 'GO'.
The variable name '@cmd' has already been declared. Variable names must be unique within a query batch or stored procedure.

SQL Transaction 내에서 GO 문을 사용하는 것은 문제가 있다고 생각합니다.

이런 식으로 실행할 때 생성된 스크립트가 작동하도록 하려면 어떻게 해야 합니까?

GO는 SQL 키워드가 아닙니다.

클라이언트 도구(SSMS 등)에서 전체 스크립트를 배치로 나누기 위해 사용하는 배치 구분자입니다.

스크립트를 직접 배치로 분할하거나 sqlcmd와 "-cGO" 또는 osql을 사용하여 "GO"를 처리해야 합니다.

트랜잭션의 이름을 지정하면 여러 GO 섹션을 포함할 수 있으며 이 섹션은 모두 하나의 단위로 롤백됩니다.예:

BEGIN TRANSACTION TransactionWithGos;
GO

SET XACT_ABORT ON; -- Roll back everything if error occurs in script
GO

-- do stuff
GO

COMMIT TRANSACTION TransactionWithGos;
GO

이 문제를 해결하는 불쌍한 사람의 방법: GO 문에서 SQL을 분할합니다.다음과 같은 것:

private static List<string> getCommands(string testDataSql)
{
    string[] splitcommands = File.ReadAllText(testDataSql).Split(new string[]{"GO\r\n"}, StringSplitOptions.RemoveEmptyEntries);
    List<string> commandList = new List<string>(splitcommands);
    return commandList;
}

[지금 작업 중인 앱에서 복사한 내용입니다.이 가룬-괴짜-티 이 코드]

그럼 그냥ExecuteNonQuery()일람표를보너스 포인트를 얻기 위해 거래를 이용합니다.

보너스 포인트

트랜잭션 비트를 처리하는 방법은 운영 목표에 따라 다릅니다.기본적으로 두 가지 방법으로 수행할 수 있습니다.

전체 실행을 단일 트랜잭션으로 래핑합니다. 이는 모든 작업을 실행하거나 실패할 경우에 적합합니다(더 나은 옵션 IMHO).

각 통화를 다음으로 넘깁니다.ExecuteNonQuery()그 자체의 거래에서.음, 사실, 각각의 통화는 그들만의 거래입니다.하지만 당신은 예외 사항을 파악하고 다음 항목으로 넘어갈 수 있습니다.물론 이것이 일반적으로 생성되는 DDL 작업이라면 다음 부품이 이전 부품에 의존하는 경우가 많기 때문에 한 부품에 오류가 발생하면 전체적인 문제가 발생할 수 있습니다.

아래 지적된 대로 배치가 실제로 올바른 위치에 tran을 지정했습니다.

문제는 GO가 배치의 끝을 나타내는 것처럼 트랜잭션 내에서 GO를 사용할 수 없고 T-SQL 명령 자체가 아니라는 것입니다.SQLCMD를 사용하여 전체 스크립트를 실행하거나 GO에서 분할하여 각 배치를 차례로 실행할 수 있습니다.

GO는 SQL에서 배치 구분자입니다.이것은 전체 배치를 완료하는 것을 의미합니다.예를 들어, 한 배치 @ID에 정의된 변수는 'GO' 문 뒤에 액세스할 수 없습니다.이해를 위해 아래 코드를 참조하십시오.

Declare @ID nvarchar(5);
set @ID = 5;
select @ID
GO
select @ID

스크립트 테스트:

  • 백업 서버에서 프로덕션 백업 복원
  • GO를 사용하여 스크립트 실행

스크립트 설치:

  • 응용 프로그램 종료
  • 단일 사용자 모드로 전환
  • 백업 데이터베이스
  • GO를 사용하여 스크립트 실행, 복원 백업 실패 시
  • 다중 사용자 모드로 돌아가기
  • 응용 프로그램 다시 시작

실제로 Microsoft를 사용할 때는 GO 문을 사용할 수 있습니다.SqlServer.관리.평활 확장:

    var script = GetScript(databaseName);
    var conn = new SqlConnection(connectionString.ConnectionString);
    var svrConnection = new ServerConnection(conn);
    var server = new Server(svrConnection);
    server.ConnectionContext.ExecuteNonQuery(script);

http://msdn.microsoft.com/de-de/library/microsoft.sqlserver.management.smo.aspx

http://www.microsoft.com/en-us/download/details.aspx?id=29065 (SQL 2012 버전)에서 배포된 SQL CLR 유형 및 SQL 관리 개체 패키지만 있으면 됩니다.

그냥 여기에 내 해결책을 추가할 생각이었는데...'GO'를 ExecuteNonQuery가 이해하는 구분자(즉, ';' 연산자)로 바꿉니다.이 기능을 사용하여 스크립트를 수정합니다.

private static string FixGoDelimitedSqlScript(string script)
{
    return script.Replace("\r\nGO\r\n", "\r\n;\r\n");
}

연산자가 ';'인 복잡한 중첩 T-SQL에서는 작동하지 않을 수 있지만, 나와 내 스크립트에서는 작동했습니다.위에 나열된 분할 방법을 사용했을 것이지만, 사용 중인 라이브러리에 제한이 있어 다른 해결 방법을 찾아야 했습니다.이것이 누군가에게 도움이 되기를 바랍니다!

PS. ';' 연산자는 문 구분 기호이고 'GO' 연산자는 배치 구분 기호이므로 고급 스크립트는 이것으로 수정되지 않을 것입니다.

언급URL : https://stackoverflow.com/questions/971177/using-go-within-a-transaction

반응형