【问题标题】:Check if a result is an integer/varchar/etc. during SQL execution?检查结果是否为整数/varchar/等。在 SQL 执行期间?
【发布时间】:2013-01-10 23:56:42
【问题描述】:

我在不同的服务器上使用MySQLMSSQL,所以我需要学习如何以两种方式做到这一点。我有一个类型为varchar 的列。通常它会填充integersfloats,但不时会填充“见注释”或类似内容的文字。我有一个查询生成器,因此用户可以将结果与数字进行比较。我可以将用户的输入从integers 转换为floats,并且在针对integersfloats, 进行测试时,SQL 会处理得很好,但是只要达到varchar,就会出现问题。

更复杂的是,用户输入在查询构建器中,所以我不能只运行 2 个单独的查询来分解事情。所以我首先需要知道的是 SQL 是如何处理查询的。在 PHP 中,如果你有一个 if 语句,并且第一个条件失败,它将永远不会继续第二个条件。例如:if($_POST && $_POST['result']) 代码不会尝试读取$_POST 的结果,因为$_POST 不存在。

如果它的工作方式相同,那么我需要一些方法来测试结果是否为整数。如果是,那么它可以继续运行脚本。但我也不知道我该怎么做。像这样的:

SELECT *
FROM my_table
WHERE ISNUMERIC(result) = 1 AND result > 4.5

因此,如果结果包含 varchar,它将在到达 result > 4.5 之前终止,这样我就不会破坏我的语句并出现错误。

谢谢。

【问题讨论】:

  • 你能再增加一列来存储你的浮点数或整数吗?
  • 我会再看看桌子的设计。通常,如果您大部分时间都需要存储数字,则将其存储在数字字段中。如果您需要存储文本,请将其存储在文本字段中。如果您需要同时存储两者,请考虑使用 2 个字段并使它们可以为空(然后用户只需要输入 1 个字段)
  • 你可以有一个 text、int 和 float 字段,有一个特殊的列,它只告诉你哪个字段被填充以避免检查空值
  • 我会回应@Greg 评论,但是如果您已经有一个包含混合数据内容的列并且您无法更改您的架构,那么您为什么真正关心 MySQL/MSSQL 级别是否该项目是一个数字或一个字符串。您不能只处理应用程序中的数字与字符串问题吗?
  • 与答案的一部分相关stackoverflow.com/questions/789231/…

标签: php mysql sql sql-server comparison


【解决方案1】:

我会再看看桌子的设计。通常,如果您大部分时间都需要存储数字,则将其存储在数字字段中。如果您需要存储文本,请将其存储在文本字段中。如果您需要同时存储两者,请考虑使用 2 个字段并使它们可以为空(然后用户只需要输入 1 个字段)

【讨论】:

    【解决方案2】:

    如果您使用的是 SQL Server,则上述查询可以正常工作。不过,您可以尝试以下替代方法:

    SELECT *
    FROM my_table 
    WHERE result > 
      CASE WHEN ISNUMERIC(result) = 1
      THEN '5'
      ELSE result
      END
    

    这是两者的SQL Fiddle

    如果您使用的是 MySQL,那么这似乎可行:

    SELECT *
    FROM my_table 
    WHERE result > 5
    

    还有SQL Fiddle

    【讨论】:

    • mysql 没有原生 ISNUMERIC 函数。
    • 我知道,OP 也标记了 SQL Server。我更新了我的答案以包括两者。谢谢
    【解决方案3】:

    我发现拥有一个函数非常有用,该函数在给定文本输入的情况下将返回 INT,如果无法解析该值,则返回 NULL。然后你可以简单地查询

    WHERE dbo.ParseInteger(result) >= 3
    

    就我而言,我只对整数感兴趣,但我相信您可以扩展它以适应浮点数。这可能比您需要的更复杂;例如,如果你不关心指数,你可以扔掉 70%。我对 MySQL 太生疏了,无法提供翻译。最后,请注意,我假设的是英文数字,​​您可能有不同的组和小数分隔符。

    CREATE FUNCTION dbo.ParseInteger(@Input VARCHAR(100)) RETURNS BIGINT WITH SCHEMABINDING
    AS BEGIN
        SET @Input = dbo.Trim(@Input)  -- If you're not worried about linebreaks or other odd chars, LTRIM(RTRIM(@Input)) will be fine
        IF ISNUMERIC(@Input) = 0 RETURN NULL
        IF @Input IN ('.', '+', '-', ',') RETURN NULL
        SET @Input = REPLACE(@Input, ',', '')  -- Strip commas
    
        DECLARE @DecimalPos INT = CHARINDEX('.', @Input)
        DECLARE @ExpPos     INT = CHARINDEX('E', @Input)
        DECLARE @IntValue   BIGINT
        IF @DecimalPos = 0 AND @ExpPos = 0
            BEGIN
            -- There's no decimal and no exponent, so we can easily cast this bog-standard integer
            SET @IntValue = CAST(@Input AS BIGINT)
            END
        ELSE IF @DecimalPos > 0 AND @ExpPos = 0
            BEGIN
            -- There's a decimal point but no exponent; we can cast the integer part, and then nudge it if necessary to round off the tenths place
            SET @IntValue = CAST(SUBSTRING(@Input, 1, @DecimalPos - 1) AS BIGINT)
            IF SUBSTRING(@Input, @DecimalPos + 1, 1) BETWEEN '5' AND '9'
                IF @IntValue < 0
                    SET @IntValue -= 1
                ELSE
                    SET @IntValue += 1
            END
        ELSE
            BEGIN
            -- There's an exponent, and probably a decimal; this will be relatively complicated
            IF @DecimalPos = 0
                BEGIN
                -- There's no decimal; insert one, just so we have consistency downstream
                SET @Input      = LEFT(@Input, @ExpPos - 1) + '.0E' + RIGHT(@Input, LEN(@Input) - @ExpPos)
                SET @DecimalPos = @ExpPos
                SET @ExpPos    += 2
                END
    
            DECLARE @Magnitude INT = CASE WHEN LEFT(@Input, 1) = '-' THEN @DecimalPos - 2 ELSE @DecimalPos - 1 END  -- For normalized scientific notation, this will always be one, but we can't expect that
            DECLARE @Exponent  INT = CAST(RIGHT(@Input, LEN(@Input) - @ExpPos) AS INT)
            IF @Exponent > 18 RETURN NULL  -- BIGINT can handle values up to 2^63, or 9.2E18
    
            SET @Input = REPLACE(SUBSTRING(@Input, 1, @ExpPos - 1), '.', '')
    
            DECLARE @MagAdjustment INT = @Magnitude + @Exponent - CASE WHEN LEFT(@Input, 1) = '-' THEN LEN(@Input) - 1 ELSE LEN(@Input) END
    
            IF @MagAdjustment > 0
                BEGIN
                SET @Input += REPLICATE('0', @MagAdjustment)
                END
            ELSE IF @MagAdjustment < 0
                BEGIN
                WHILE -@MagAdjustment > @Magnitude AND LEN(@Input) > 1
                    BEGIN
                    SET @MagAdjustment += 1
                    SET @Input          = SUBSTRING(@Input, 1, LEN(@Input) - 1)
                    END
    
                    IF -@MagAdjustment > @Magnitude SET @Input = '0'
                ELSE IF -@MagAdjustment = @Magnitude SET @Input = CASE WHEN LEFT(@Input, 1) BETWEEN '5' AND '9' THEN '1' WHEN LEFT(@Input, 2) BETWEEN '-5' AND '-9' THEN '-1' ELSE '0' END
                ELSE                                 SET @Input = SUBSTRING(@Input, 1, CASE WHEN LEFT(@Input, 1) = '-' THEN 1 ELSE 0 END + LEN(@Input) + @MagAdjustment)
                END
    
            SET @IntValue = CAST(@Input AS BIGINT)
            END
    
        RETURN @IntValue
    END
    

    【讨论】:

      猜你喜欢
      • 2011-06-03
      • 2022-08-17
      • 1970-01-01
      • 2016-04-14
      • 1970-01-01
      • 2015-08-29
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      相关资源
      最近更新 更多