2012-03-27 4 views
1

SQL에 상당히 익숙하며 SQL 스크립트에 혼란을 야기하는 키워드에 문제가 있습니다. C#에서 premade .sql 스크립트 파일 목록을 실행하려고합니다. 나는 현재 파일을 문자열로 읽고 command.ExecuteNonQuery()로 실행하고있다. 이 스크립트의 가장 위대한 작품,하지만 난 실수로 키워드를 포함하는 하나의 실행 해요 : 그것은 그 명령이 실패 GO 칠 때, 기본적으로SQL 스크립트 데이터가 프로그래밍 방식으로 실행될 때 문제를 일으키는 키워드 - C#

INSERT INTO [thetable] 
SELECT '123123', 'abcabc', 'I WANT TO GO TO BED' 
UNION ALL 
SELECT '123124', 'abcdef', 'SOOO TIRED' 

.

필자는 이러한 삽입 파일을 작성하는 책임이 있으므로 어떤 방식 으로든 다시 포맷해야하는 경우 가능합니다. 그러나 그 안에있는 데이터는 협상 할 수 없습니다. 또한, 많은 행이있는 파일에서로드하고 있기 때문에 매개 변수화를 피하기 위해 실행 가능하지 않습니다.

이 시점에서 도움을 주시면 감사하겠습니다. 고마워요!

편집이 정보 추가 :

명확히하기 위해, 실제 문자열은 더 'ASVFDS4 + 23eF3da34sddsdf3d3t4g ... 100charslater ... sd5OAyGOsiISIssdsd/sNUIGsdisd354f'같은 것입니다. 5OAy 즉시 GOsiIS 뒤에 것을

"Unclosed quotation mark after character string 'ASVFDS4+23eF3da34sddsdf3d3t4g...100charslater...sd5OAy' 

참고 ..., 이동 실제로 명령으로 읽어되고 있음을 믿고 저를 인도한다 : 나는 시도하고 명령을 실행할 때, 나는 말한다 예외를 잡을 그 명령 전에 문자열의 끝을 예상하게합니다. 나는 또한 명확히해야 .NET 3.5

편집 2 실행

, 나는 현재 실제 GO 문에 분할 및 개별적으로 명령을 실행하고 있습니다.

USE MyDatabase 
GO 
INSERT INTO [thetable] 
SELECT '123123', 'abcabc', 'I WANT TO GO TO BED' 
UNION ALL 
SELECT '123124', 'abcdef', 'SOOO TIRED' 
UNION ALL 
... 
SELECT '123189', 'abcabc', 'HAD SOME SLEEP' 
GO 

스플릿, 그래서 I 별도로

USE MyDatabase 

INSERT INTO [thetable] 
SELECT '123123', 'abcabc', 'I WANT TO GO TO BED' 
UNION ALL 
SELECT '123124', 'abcdef', 'SOOO TIRED' 
UNION ALL 
... 
SELECT '123189', 'abcabc', 'HAD SOME SLEEP' 

실행한다. 그래서 내 문제는 실제 GO 명령문이 아니며, 'GO'문자가 데이터 문자열에 나타납니다.

답변 : 문제는 내가 정말 바보 같은 실수를 한 것입니다. 나는 "GO"에 나뉘 었는데, 이것은 문자가 나오는 그 매개 변수의 중간에서 명령 문자열을 바로 나눕니다. 도움의 모든

/마른 세수는

감사합니다!

+0

예외는 무엇입니까? 나는 당신이 가지고있는 문제가 위의 SQL에서 보여지는 적어도 키워드가되는 것과 관련이 있다는 것을 매우 의심한다. 나는 그것이 아포스트로피 또는 다른 것 같아요. – Andrew

+1

일부 애플리케이션에서는 'GO'가 배치 분리기로 사용됩니다. 'command.ExecuteNonQuery()'가'GO'를 인식한다고 생각하지 마십시오. 아마도 SQL 스크립트를 파싱하고 한 번에 하나의 배치를 실행하는 C# 코드가 있을까요? 이 문제를 해결할 방법을 찾아야합니다. 자신을 코딩하고 스크립트 파일의 생성을 제어 할 수 있다면'GO '가 한 줄에있을 때만 새로운 배치를 시작하도록 코드를 변경할 수 있습니다. –

+0

어떤 데이터베이스를 사용하고 있습니까? SQL Server이고 개발자 버전 이상인 경우. SQL 프로파일 러를 실행하여 서버에서 실행중인 SQL을 확인하십시오. – Andrew

답변

1

GO를 인식하고 파일을 일괄 처리로 분할 한 다음 개별적으로 실행해야합니다.

GO 행을 인식하려면 m/^ \ s + GO \ s + $/i와 같은 정규식을 사용하십시오.

+0

내가 실제로이 일을하고있는 것이 재밌다. .Split (새 문자열 [] { "GO"}, StringSplitOptions.RemoveEmptyEntries). 위의 문자열 필드를 스크립트에서 분리하여 문자가 나오는 것을 보았 기 때문에 이것은 예상했던 것보다 효과적으로 작동했습니다. 따라서 .Split에서 반환 된 명령 문자열 목록에서 명령 중 하나가 문자열 필드의 중간에서 절반으로 분할되었습니다. 오케이. 이 문제는 으로 변경 한 후 수정되었습니다 .Split (새 문자열 [] \ "\ r \ nGO"}, StringSplitOptions.RemoveEmptyEntries) – MarnBeast

4

'go'("smth go smth") 등으로 주석 및 문자열 값을 가진 Sql 스크립트를 구문 분석해야하는 경우 gplex 도구를 사용할 수 있습니다. SQL 스크립트 구문 분석을위한 Gplex 규칙 :

%namespace LexScanner 
%option verbose, summary, noparser, unicode 

%x QUOTE 
%x COMMENT 

%{ 
    static string line = ""; 
    static List<string> butch = new List<string>(); 
    enum TokenType { 
     SL_COMMENT, 
     ML_COMMENT, 
     STRING, 
     WORD, 
     OTHER, 
     ending 
    }; 
%} 

dotchr [^\r\n] 
eol (\r\n?|\n) 
%% 
\-\-[^\n]*$    { add(yytext, TokenType.SL_COMMENT); } 

\/\*     { add(yytext, TokenType.ML_COMMENT); BEGIN(COMMENT); } 
<COMMENT>\*\/   { add(yytext, TokenType.ML_COMMENT); BEGIN(INITIAL); } 
<COMMENT>[^\*]+   { add(yytext, TokenType.ML_COMMENT); } 
<COMMENT>\*    { add(yytext, TokenType.ML_COMMENT); } 

\'      { add(yytext, TokenType.STRING); BEGIN(QUOTE); } 
<QUOTE>\'\'    { add(yytext, TokenType.STRING); } 
<QUOTE>[^\']+   { add(yytext, TokenType.STRING); } 
<QUOTE>\'    { add(yytext, TokenType.STRING); BEGIN(INITIAL); } 

[gG][oO]    { push(); } 

[a-zA-Z0-9]+   { add(yytext, TokenType.WORD); } 
.      { add(yytext, TokenType.OTHER); } 
\r?\n     { add(yytext, TokenType.OTHER); } 
<<EOF>>     { push(); } 
%% 

그런 다음 C# 클래스를 생성하여 사용합니다.

편집 :
사용 방법에 대한 의견이 더 있습니다.
기능 add(string text, TokenType token)push() - 구문 분석 된 문자열로 수행 할 작업. 추가() 함수는 GO 키워드 사이의 문자열을 구문 분석 및 출력 파일에 결과를 기록 수집합니다 (단 제어) :

private void add(string text, TokenType token) 
{ 
    //write to the file for output control (for test only) 
    using (StreamWriter str = new StreamWriter("C:\\temp\\temp.txt", true)) 
    { 
     str.WriteLine(token + " : " + text); 
    } 
    line += text; 
} 

푸시() 실행을 위해 부치 문자열을 수집합니다

private void push() 
{ 
    //write to the file for output control (for test only) 
    using (StreamWriter str = new StreamWriter("C:\\temp\\butch.txt", true)) 
    { 
     str.WriteLine("GO: " + line); 
    } 

    butch.Add(line); 
    line = ""; 
} 

이 클래스를 사용하려면 C# 코드에서 엔트리 포인트를 지정해야합니다. 예 :

public static List<string> ParseFile(String fileToParse) 
{ 
    int tok; 
    Scanner scnr = new Scanner(); 
    scnr.SetSource(fileToParse, 0); 
    do { 
      tok = scnr.yylex(); 
     } while (tok > (int)Tokens.EOF); 
    return butch; 
} 

독립 실행 형 응용 프로그램으로 사용하려면 Main 함수를 정의하십시오.

위의 코드는 모두 .lex 파일에 저장해야합니다. 파일 sqlparser.cs은 명령 줄에서 호출하여 생성됩니다

gplex sqlparser.lex 

Gplex 좋은 문서와 그것을 사용하는 방법을 예제를 가지고있다.

+0

C#에서 자세한 사용법 (푸시 방법 추가) 이것은 확실히가는 길입니다,하지만 저는 렉스와 함께 전문가가 아닙니다 ... 고마워요! – Swell

+0

@Swell 게시물을 업데이트했습니다. 이게 도움이 되길 바란다. – Natalya

+0

완벽하고 매력적인 작품! 고마워. – Swell