복붙노트

[SQL] 는 SQL 쿼리에 사용되는 테이블 목록

SQL

는 SQL 쿼리에 사용되는 테이블 목록

SQL 쿼리에서 사용되는 테이블의 목록을 얻을 수있는 방법을 방법이 있나요? 예 : 내가 좋아하는 뭔가를 :

SELECT * FROM Table t JOIN OtherTable ON t.id=OtherTable.t_id

내가 얻을 기대

Table, OtherTable

감사

해결법

  1. ==============================

    1.당신은 당신의 쿼리 후이 SQL 스크립트 권한을 사용할 수 있습니다. 그것은 마지막으로 실행 된 쿼리에 사용되는 테이블의 목록을 반환합니다 :

    당신은 당신의 쿼리 후이 SQL 스크립트 권한을 사용할 수 있습니다. 그것은 마지막으로 실행 된 쿼리에 사용되는 테이블의 목록을 반환합니다 :

       SELECT Field1, Field2 
       FROM Table t JOIN OtherTable ON t.id=OtherTable.t_id
    
      ;WITH vwQueryStats AS(
         SELECT 
          COALESCE(OBJECT_NAME(s2.objectid),'Ad-Hoc') AS ProcName
          ,execution_count
          ,s2.objectid
          ,(
             SELECT TOP 1 
                SUBSTRING(s2.TEXT,statement_start_offset / 2+1 
                ,( ( CASE WHEN statement_end_offset = -1
                    THEN (LEN(CONVERT(NVARCHAR(MAX),s2.TEXT)) * 2)
                    ELSE statement_end_offset END)- statement_start_offset) / 2+1)) AS sql_statement
                ,last_execution_time
             FROM sys.dm_exec_query_stats AS s1
             CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS s2
        )
        SELECT TOP 1 * 
        INTO #lastQueryStats
        FROM vwQueryStats x
        WHERE sql_statement NOT like 'WITH vwQueryStats AS%'
        ORDER BY last_execution_time DESC
    
        SELECT
        TABLE_NAME
        FROM #lastQueryStats, INFORMATION_SCHEMA.TABLES tab 
        WHERE CHARINDEX( tab.TABLE_NAME, sql_statement) > 0
    
    
        DROP TABLE #lastQueryStats 
    

    이 게시물에서 마지막으로 실행 된 쿼리를 검색하는 쿼리를 촬영했습니다 그리고 난 당신의 예제와 일치하도록 조금 수정했습니다.

    당신이 요청에 따라 출력 될 것입니다 :

     Table
     OtherTable
    

    당신이 할 경우 그 쉼표는 당신이 할 수있는 분리 :

    DECLARE @tableNames VARCHAR(MAX) 
    
    SELECT @tableNames = COALESCE(@tableNames + ', ', '') + TABLE_NAME
    FROM   #lastQueryStats, INFORMATION_SCHEMA.TABLES tab 
    WHERE  CHARINDEX( tab.TABLE_NAME, sql_statement) > 0
    
    SELECT @tableNames 
    

    쿼리의 수천을 가진 '보통'생산 QA 환경에서 동시에 다른 쿼리로하지 작업이 첫 번째 쿼리와 쿼리 사이에서 실행될 수있는이 힘을 실행 한 그러나 당신이 조심해야 dB 통계에서 추출 정보를 그.

    희망이 도움이

  2. ==============================

    2.다음 : C #을 사용 하나 개의 솔루션은 수입 Microsoft.SqlServer.TransactSql.ScriptDom이다 (\ Program 파일 (x 86) \ Microsoft SQL Server를 \ 120 \ SDK \ 어셈블리 \ Microsoft.SqlServer.TransactSql.ScriptDom.dll 나는 C에서 DLL을 찾을 수 없음) 다음을 수행 :

    다음 : C #을 사용 하나 개의 솔루션은 수입 Microsoft.SqlServer.TransactSql.ScriptDom이다 (\ Program 파일 (x 86) \ Microsoft SQL Server를 \ 120 \ SDK \ 어셈블리 \ Microsoft.SqlServer.TransactSql.ScriptDom.dll 나는 C에서 DLL을 찾을 수 없음) 다음을 수행 :

    private List<string> GetTableNamesFromQueryString(string query)
    {
        IList<ParseError> errors = new List<ParseError>();
        IList<TSqlParserToken> queryTokens;
        List<string> output = new List<string>(16);
        StringBuilder sb = new StringBuilder(128);
        TSql120Parser parser = new TSql120Parser(true);
        TSqlTokenType[] fromTokenTypes = new TSqlTokenType[2]
            {
                TSqlTokenType.From,
                TSqlTokenType.Join
            };
        TSqlTokenType[] identifierTokenTypes = new TSqlTokenType[2]
            {
                TSqlTokenType.Identifier,
                TSqlTokenType.QuotedIdentifier
            };
    
        using (System.IO.TextReader tReader = new System.IO.StringReader(query))
        {
            queryTokens = parser.GetTokenStream(tReader, out errors);
            if (errors.Count > 0) { return errors.Select(e=>"Error: " + e.Number + " Line: " + e.Line + " Column: " + e.Column + " Offset: " + e.Offset + " Message: " + e.Message).ToList(); }
    
            for (int i = 0; i < queryTokens.Count; i++)
            {
                if(fromTokenTypes.Contains(queryTokens[i].TokenType))
                {
                    for (int j = i + 1; j < queryTokens.Count; j++)
                    {
                        if (queryTokens[j].TokenType == TSqlTokenType.WhiteSpace) { continue; }
                        else if (identifierTokenTypes.Contains(queryTokens[j].TokenType))
                        {
                            sb.Clear();
    
                            GetQuotedIdentifier(queryTokens[j], sb);            //Change Identifiers to QuotedIdentifier (text only)
    
                            while (j + 2 < queryTokens.Count && queryTokens[j + 1].TokenType == TSqlTokenType.Dot && identifierTokenTypes.Contains(queryTokens[j + 2].TokenType))
                            {
                                sb.Append(queryTokens[j + 1].Text);
                                GetQuotedIdentifier(queryTokens[j + 2], sb);    //Change Identifiers to QuotedIdentifier (text only)
    
                                j += 2;
                            }
    
                            output.Add(sb.ToString());
                            break;              //exit the loop
                        }
                        else { break; }             //exit the loop if token is not a FROM, a JOIN, or white space.
                    }
    
                }
            }
    
            return output.Distinct().OrderBy(tableName => tableName).ToList();
        }
    }
    
    private void GetQuotedIdentifier(TSqlParserToken token, StringBuilder sb)
    {
        switch(token.TokenType)
        {
            case TSqlTokenType.Identifier: sb.Append('[').Append(token.Text).Append(']'); return;
            case TSqlTokenType.QuotedIdentifier: sb.Append(token.Text); return;
            default: throw new ArgumentException("Error: expected TokenType of token should be TSqlTokenType.Identifier or TSqlTokenType.QuotedIdentifier");
        }
    }
    

    나는 일이 답변을 얻을려고 후에이 함께했다.

  3. ==============================

    3.아래의 코드는 Trisped의 답변에 따라,하지만 스키마 이름을 생략 완전한 테이블 이름, 그리고 몇 가지 정리 / 최적화와 함께 작동하도록 수정 :

    아래의 코드는 Trisped의 답변에 따라,하지만 스키마 이름을 생략 완전한 테이블 이름, 그리고 몇 가지 정리 / 최적화와 함께 작동하도록 수정 :

    public class Parser
    {
        public static List<string> GetTableNamesFromQueryString(string query)
        {
            var output = new List<string>();
            var sb = new StringBuilder();
            var parser = new TSql120Parser(true);
    
            var fromTokenTypes = new[]
            {
                TSqlTokenType.From,
                TSqlTokenType.Join
            };
    
            var identifierTokenTypes = new[]
            {
                TSqlTokenType.Identifier,
                TSqlTokenType.QuotedIdentifier
            };
    
            using (System.IO.TextReader tReader = new System.IO.StringReader(query))
            {
                IList<ParseError> errors;
                var queryTokens = parser.GetTokenStream(tReader, out errors);
                if (errors.Any())
                {
                    return errors
                        .Select(e => string.Format("Error: {0}; Line: {1}; Column: {2}; Offset: {3};  Message: {4};", e.Number, e.Line, e.Column, e.Offset, e.Message))
                        .ToList();
                }
    
                for (var i = 0; i < queryTokens.Count; i++)
                {
                    if (fromTokenTypes.Contains(queryTokens[i].TokenType))
                    {
                        for (var j = i + 1; j < queryTokens.Count; j++)
                        {
                            if (queryTokens[j].TokenType == TSqlTokenType.WhiteSpace)
                            {
                                continue;
                            }
    
                            if (identifierTokenTypes.Contains(queryTokens[j].TokenType))
                            {
                                sb.Clear();
                                GetQuotedIdentifier(queryTokens[j], sb);
    
                                while (j + 2 < queryTokens.Count 
                                    && queryTokens[j + 1].TokenType == TSqlTokenType.Dot 
                                    && (queryTokens[j + 2].TokenType == TSqlTokenType.Dot || identifierTokenTypes.Contains(queryTokens[j + 2].TokenType)))
                                {
                                    sb.Append(queryTokens[j + 1].Text);
    
                                    if (queryTokens[j + 2].TokenType == TSqlTokenType.Dot)
                                    {
                                        if (queryTokens[j - 1].TokenType == TSqlTokenType.Dot) 
                                            GetQuotedIdentifier(queryTokens[j + 1], sb);
    
                                        j++;
    
                                    }
                                    else
                                    {
                                        GetQuotedIdentifier(queryTokens[j + 2], sb);
                                        j += 2;
                                    }
                                }
    
                                output.Add(sb.ToString());
                            }
                            break;
                        }
                    }
                }
    
                return output.Distinct().OrderBy(tableName => tableName).ToList();
            }
        }
    
        private static void GetQuotedIdentifier(TSqlParserToken token, StringBuilder sb)
        {
            switch (token.TokenType)
            {
                case TSqlTokenType.Identifier: 
                    sb.Append('[').Append(token.Text).Append(']'); 
                    break;
                case TSqlTokenType.QuotedIdentifier:
                case TSqlTokenType.Dot: 
                    sb.Append(token.Text); 
                    break;
    
                default: throw new ArgumentException("Error: expected TokenType of token should be TSqlTokenType.Dot, TSqlTokenType.Identifier, or TSqlTokenType.QuotedIdentifier");
            }
        }
    }
    
  4. ==============================

    4.당신이 이것을 달성 할 수있는 하나의 hackish 방법은 명시 적으로 쿼리의 필드 이름과 테이블 이름, 예를 들어, 그들을 앞에하는 것

    당신이 이것을 달성 할 수있는 하나의 hackish 방법은 명시 적으로 쿼리의 필드 이름과 테이블 이름, 예를 들어, 그들을 앞에하는 것

    SELECT Field1 As "OtherTable.Field1",
           Field2 As "Table.Field2"
    FROM Table t JOIN OtherTable ON t.id=OtherTable.t_id
    

    기본적으로, 당신은 쿼리 결과에 자신의 메타 데이터를 제공하고 있습니다. 쿼리가 반환 된 후, 열 이름을보고 테이블 이름을 분할하는 사용자 지정 논리를 구현합니다.

  5. ==============================

    5.Trisped의 솔루션은 완벽하게 작동합니다. 나는 사례를 구분을 보장하고 괄호를 트리밍 한 줄을 수정했습니다.

    Trisped의 솔루션은 완벽하게 작동합니다. 나는 사례를 구분을 보장하고 괄호를 트리밍 한 줄을 수정했습니다.

    OLD : output.Add (sb.ToString ());

    (.. sb.ToString () ToLower는 () 트림 (새 문자 [{ "[", "]})) : NEW output.Add;

  6. from https://stackoverflow.com/questions/16692344/list-of-tables-used-in-an-sql-query by cc-by-sa and MIT license