AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 329209
Accepted
Michael Green
Michael Green
Asked: 2023-07-12 20:32:30 +0800 CST2023-07-12 20:32:30 +0800 CST 2023-07-12 20:32:30 +0800 CST

Encontre varchars "nus"

  • 772

É claro que omitir o comprimento de um varchar é uma coisa ruim . Infelizmente agora estou trabalhando com uma base de código onde isso aconteceu. Extensivamente. Eu gostaria de corrigir isso. O primeiro passo será encontrar as ocorrências. É aqui que preciso de ajuda.

Pesquisas em vários mecanismos da web usando todos os sinônimos que consigo imaginar não retornam nenhuma resposta oficial. estou pedindo

  • casos de teste adicionais que perdi
  • uma maneira abrangente e canônica de encontrar declarações sem extensão

Qualquer tecnologia normalmente disponível em um ambiente de desenvolvimento Windows (SSMS, Powershell, .Net etc.) é boa. Respostas que empregassem mais tecnologias de nicho seriam interessantes para a comunidade em geral, mas nem tanto para mim, pessoalmente.

Testes

Como os quatro tipos de dados em questão - char, nchar, varchar e nvarchar - terminam todos com os caracteres CHAR, utilizo isso sozinho nos testes abaixo. Isso evita o inchaço da lista e simplifica a adição de mais testes. Será fácil copiar, colar e substituir, caso seja necessário.

-- These are all legal; the regex must not return these
char(9)
char (9)            -- with a space
char    (9)         -- with a tab
char         (9)    -- tab space tab space
char(max)
char
(9)                 -- a new line between type and length

character(9)
CAST(999 AS character(9))

char varying(9)
character varying(9)
CAST(999 AS char varying(9))
CAST(999 AS character varying(9))


-- These also are legal; ugly, but legal
[char](9)
[char] (9)          -- with a space
[char]  (9)         -- with a tab
[char]       (9)    -- tab space tab space
[char](max)
[char]
(9)                 -- a new line between type and length

-- The type can also be delimited by double-quote
"char"(9)
-- All the tests using square brackets should be duplicated with other delimiters.

[character](9)
CAST(999 AS [character](9))

-- SQL Server 2022 throws an error for [character varying]
-- Msg 243, Level 16, State 1, Line 15
-- Type character varying is not a defined system type.


-- These are business terms which the regex should not return
characteristic
charge
chart

-- These are valid SQL but missing the length. These are what the search should return
char;
char ;      -- a space
char    ;   -- a tab
char,
char ,
char = 'lorem'
cast(9 as char)
convert(char, 9)

[char];
[char] ;        -- a space
[char]  ;   -- a tab
[char],
[char] ,
[char] = 'lorem'
cast(9 as [char])
convert([char], 9)

character
CAST(999 AS character)

char varying
character varying
CAST(999 AS char varying)
CAST(999 AS character varying)

sql-server
  • 3 3 respostas
  • 123 Views

3 respostas

  • Voted
  1. Best Answer
    Zikato
    2023-07-18T23:19:08+08:002023-07-18T23:19:08+08:00

    Regex não é a maneira correta de fazer isso. Sempre haverá falsos positivos que são impossíveis/extremamente difíceis de encontrar. Por exemplo, blocos de comentários multilinha

    Em vez disso, recomendo usar o SqlScriptDOM , que é uma biblioteca .NET para analisar instruções T-SQL e interagir com sua árvore de sintaxe abstrata fornecida pela Microsoft.

    Em seguida, você pode usar um aplicativo .NET ou PowerShell para identificar exatamente o tamanho do caractere ausente.

    Você pode iterar sua base de código no controle de origem ou sys.sql_modules e passar o conteúdo para a função ScriptDOM.

    Peguei emprestado a maior parte do código do blog de Dan Guzman

    # this is the script to parse
    $script = @"
    -- These are all legal; the regex must not return these
    
    declare @test char(20)
    
    SET @test = CAST (@test AS char     (15 )) /* CHAR( 15 ) is intentional */
    DECLARE @test2 char
    (
        100
    )
    
    RAISERROR ('Char(max) is not valid',16 ,1) WITH nowait
    SELECT CHAR(64) AS EmailSeparator -- this char(64) returns @
    
    CREATE TABLE #UglyLegal
    (
        a [char](9)
        , b [char] (9)          -- with a space
        , c [char]  (9)         -- with a tab
        , d [char]       (9)    -- tab space tab space
        , e [char]
    (9)   
        , characteristic int
        , charge bit
        , chart bit
    )
    
    
    -- These are errors that will be returned
    declare @a char;
    GO
    declare @a char ;      -- a space
    GO
    declare @a char    ;   -- a tab
    GO
    declare @a char, @b bit
    GO
    declare @a char , @b bit
    GO
    declare @a char = 'lorem'
    GO
    SELECT cast(9 as char)
    GO
    SELECT CONVERT(char, 9)
    
    CREATE TABLE #CharFamily
    (
        a char(10)
        , b char
        , c nchar(10)
        , d nchar
        , e varchar(MAX)
        , f varchar
        , g nvarchar(10)
        , h nvarchar
    )
    
    /* these examples are courtesy of Paul White https://sql.kiwi/ */
    DECLARE @foo char varying = 'aaron';
    SELECT foo = @foo, lenfoo = LEN(@foo);
    SELECT LEN(CAST(REPLICATE('a', 255) AS char varying));
    GO
    DECLARE @foo "varchar" = 'aaron';
    SELECT foo = @foo, lenfoo = LEN(@foo);
    SELECT LEN(CAST(REPLICATE('a', 255) AS "varchar"));
    "@
    
    try {
    
        class MyVisitor: Microsoft.SqlServer.TransactSql.ScriptDom.TSqlConcreteFragmentVisitor {
    
            [void]Visit ([Microsoft.SqlServer.TransactSql.ScriptDom.SqlDataTypeReference] $fragment) {
                # Write-Host "$($fragment.SqlDataTypeOption) - size $(($fragment.Parameters[0]).Value) found at line $($fragment.StartLine), column $($fragment.StartColumn), length $($fragment.FragmentLength)" -ForegroundColor Yellow
    
                if (!($fragment.Parameters[0].Value) -and $fragment.SqlDataTypeOption -in ('Char', 'NChar', 'VarChar', 'NVarChar')) {
                    Write-Host "Data type $($fragment.SqlDataTypeOption) is missing size at line $($fragment.StartLine), column $($fragment.StartColumn), length $($fragment.FragmentLength)" -ForegroundColor Red
                }
            }
    
        }
        
        # Create trusted NuGet package source, if needed
        $packageSource = Get-PackageSource | Where-Object { ($_.Location -EQ "https://www.nuget.org/api/v2") -and ($_.ProviderName -eq "NuGet") -and ($_.IsTrusted -eq $true) }
        if ($packageSource -eq $null) {
            Register-PackageSource NuGetV2 https://www.nuget.org/api/v2 -ProviderName NuGet -Trusted
        }
    
        # Install package, if needed.
        $tSqlScriptDomPackage = Install-Package Microsoft.SqlServer.TransactSql.ScriptDom -Source ($packageSource.Name) -Scope CurrentUser
        # Get package
        $tSqlScriptDomPackage = Get-Package -Name Microsoft.SqlServer.TransactSql.ScriptDom
    
        # Load Microsoft.SqlServer.TransactSql.ScriptDom.dll .NET framework assembly into app domain for use in PS scripts
        $tSqlScriptDomPackageFolderPath = [System.IO.Path]::GetDirectoryName($tSqlScriptDomPackage.Source)
        Add-Type -LiteralPath "$tSqlScriptDomPackageFolderPath\lib\net462\Microsoft.SqlServer.TransactSql.ScriptDom.dll"
        $parser = New-Object Microsoft.SqlServer.TransactSql.ScriptDom.TSql150Parser($true) # Find the correct compatibility level https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-database-transact-sql-compatibility-level?view=sql-server-ver16#compatibility_level--160--150--140--130--120--110--100--90--80- */
    
        # create an ParseError collection for any errors returned by parser
        $parseErrors = New-Object System.Collections.Generic.List[Microsoft.SqlServer.TransactSql.ScriptDom.ParseError]
    
        # create a StringReader for the script for parsing
        $stringReader = New-Object System.IO.StringReader($script)
    
        # parse the script
        $tSqlFragment = $parser.Parse($stringReader, [ref]$parseErrors)
    
        # raise an exception if any parsing errors occur
        if ($parseErrors.Count -gt 0) {
            throw "$($parseErrors.Count) parsing error(s): $(($parseErrors | ConvertTo-Json))"
        }
            
        $visitor = [MyVisitor]::new()
        $tSqlFragment.Accept($visitor)
    
    }
    catch {
        throw
    } 
    

    Aqui estou usando o TSql150Parser, que corresponde ao SQL Server 2019 de acordo com a tabela de níveis de compatibilidade

    Esta seria a saída

    Data type Char is missing size at line 29, column 12, length 4
    Data type Char is missing size at line 31, column 12, length 4
    Data type Char is missing size at line 33, column 12, length 4
    Data type Char is missing size at line 35, column 12, length 4
    Data type Char is missing size at line 37, column 12, length 4
    Data type Char is missing size at line 39, column 12, length 4
    Data type Char is missing size at line 41, column 18, length 4
    Data type Char is missing size at line 43, column 16, length 4
    Data type Char is missing size at line 48, column 9, length 4
    Data type NChar is missing size at line 50, column 9, length 5
    Data type VarChar is missing size at line 52, column 9, length 7
    Data type NVarChar is missing size at line 54, column 9, length 8
    Data type VarChar is missing size at line 58, column 14, length 12
    Data type VarChar is missing size at line 60, column 40, length 12
    Data type VarChar is missing size at line 62, column 14, length 9
    Data type VarChar is missing size at line 64, column 40, length 9
    
    • 6
  2. Michael Green
    2023-07-12T20:32:30+08:002023-07-12T20:32:30+08:00

    O SQL Server Management Studio (SSMS) permite o uso de regex em pesquisas. Minhas habilidades nisso são mínimas. O que eu tenho é isso

      char[^agt\(]]?\s*(?!(\s|\(|\]))
    

    charé o tipo de dados em questão e o sufixo para varchar e nvarchar.

    [^agt\(]impede a correspondência nos termos comerciais listados acima. Incluí apenas as três letras necessárias para meu corpus atual. Numa aplicação diferente, estes termos poderiam ser expandidos ou totalmente omitidos. Tive que incluir o parêntese esquerdo (escapou como \(), caso contrário char(..teria sido correspondido.

    ]?permite zero ou um colchete direito.

    \s*permite zero, um ou mais caracteres de espaço em branco.

    (?!)é uma previsão negativa . Significa "não seguido por". Eu realmente só quero um parêntese esquerdo aqui, mas tive que criar uma lista or ( ( | | )) incluindo espaço em branco ( \s) e quadrado direito ( \]) para obter as correspondências desejadas.

    Isso resultou principalmente de tentativa e erro. A avaliação gananciosa/preguiçosa especialmente me confundiu. Eu adoraria ter sugestões de melhorias.

    • 1
  3. Akina
    2023-07-12T21:09:10+08:002023-07-12T21:09:10+08:00

    Teste isso:

    \bn?(var)?char[]]?\s*\(\d+\)
    

    https://regex101.com/r/bTLmR9/3

    PS. Os erros devem ser verificados separadamente.

    • 0

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve