AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 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

查找“裸”varchar

  • 772

很明显,省略 varchar 的长度是一件坏事。不幸的是,我现在正在使用发生这种情况的代码库。广泛地。我想纠正这一点。第一步是查找出现的情况。这就是我需要帮助的地方。

使用我能想到的所有同义词在各种网络引擎上进行搜索都没有返回权威答案。我要问的是

  • 我错过的其他测试用例
  • 一种全面、规范的查找无长度声明的方法

通常在 Windows 开发环境(SSMS、Powershell、.Net 等)上可用的任何技术都是好的。采用更多利基技术的答案对于更广泛的社区来说会很有趣,但对我个人来说就不那么有趣了。

测试

由于所讨论的四种数据类型 - char、nchar、varchar 和 nvarchar - 都以字符 CHAR 结尾,因此我在下面的测试中单独使用它。这可以避免列表变得臃肿,并使添加更多测试变得更简单。如果需要的话,复制-粘贴-替换会很容易。

-- 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 个回答
  • 123 Views

3 个回答

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

    正则表达式不是解决此问题的正确方法。总会有不可能/极难发现的误报。例如,多行注释块

    相反,我建议使用SqlScriptDOM,它是一个 .NET 库,用于解析 T-SQL 语句并与其 Microsoft 提供的抽象语法树进行交互。

    然后,您可以使用 .NET 应用程序或 PowerShell 来准确识别丢失的字符大小。

    您可以在源代码管理或sys.sql_modules中迭代代码库,并将内容传递给 ScriptDOM 函数。

    我从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
    } 
    

    这里我使用的是TSql150Parser,它根据兼容性级别表匹配 SQL Server 2019

    这将是输出

    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

    SQL Server Management Studio (SSMS) 允许在搜索中使用正则表达式。我在这方面的技能微乎其微。我有的是这个

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

    char是有问题的数据类型,后缀为 varchar 和 nvarchar。

    [^agt\(]防止匹配上面列出的业务术语。我只包含了当前语料库所需的三个字母。在不同的应用中,这些术语可以被扩展或完全省略。我必须包含左括号(转义为\(),否则char(..会匹配。

    ]?允许零个或一个右方括号。

    \s*允许零个、一个或多个空白字符。

    (?!)是一个消极的前瞻。意思是“不跟随”。我真的只想要一个左括号,但必须创建一个( | | )包含空格 ( \s) 和右方 () 的或列表 ( \]) 才能获得所需的匹配。

    这主要是由于反复试验造成的。贪婪/懒惰的评估尤其让我失望。我很想得到改进建议。

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

    测试一下:

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

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

    附言。应单独检查错误。

    • 0

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

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

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve