在 PHP Laravel 中的 SQL Server 中将字符串转换为日期数据类型

Posted

技术标签:

【中文标题】在 PHP Laravel 中的 SQL Server 中将字符串转换为日期数据类型【英文标题】:Convert string to date datatype in SQL Server in PHP Laravel 【发布时间】:2020-08-20 20:24:09 【问题描述】:

我试图在特定日期范围内通过 id 获取产品,但我面临的问题是:

    日期为字符串格式 由于某些奇怪的原因,日期以不完整的时间戳(例如:'12-04-2020 12:21')存储在数据库中,我正试图摆脱它

使用 Laravel 的 Eloquent 下面的查询可以在没有最后一行 (AND...) 的情况下工作,这是我执行日期转换的尝试。

我也许可以用 mysql 解决这个问题,但目前的任务是使用 SQL Server,不太确定这里出了什么问题,任何帮助都是非常可观的。

$id = 2;
$from = '01-03-2020';
$to = '01-05-2020';



            $products = DB::select("SELECT DISTINCT
                                products.PRODUCT_ID,
                                products.PRODUCT_NAME,
                                TRANSACTIONS_DTL.PRODUCT_ID,
                                TRANSACTIONS_DTL.TRANS_ID,
                                TRANSACTIONS_DTL.PRODUCT_VALUE,
                                TRANSACTIONS_HD.TRANS_ID,
                                TRANSACTIONS_HD.TRANS_DATE
                             FROM
                             products
                                INNER JOIN TRANSACTIONS_DTL ON products.PRODUCT_ID = TRANSACTIONS_DTL.PRODUCT_ID
                                INNER JOIN TRANSACTIONS_HD ON TRANSACTIONS_DTL.TRANS_ID = TRANSACTIONS_HD.TRANS_ID
                             WHERE
                                products.PRODUCT_ID = $id 
                            AND TRANSACTIONS_HD.TRANS_DATE > CONVERT(date,'$from') AND TRANSACTIONS_HD.TRANS_DATE < CONVERT(date,'$to')
        ");

【问题讨论】:

TRANSACTIONS_HD.TRANS_DATE 列的实际数据类型是什么? 【参考方案1】:

您似乎将datetime 值作为文本存储在表格中(如果可能,请尝试解决该问题)。因此,要找到解决问题的方法,您可以尝试以下方法:

使用适当的style 转换列TRANSACTIONS_HD.TRANS_DATE 中的值。 对$from$to 变量中的日期使用明确的格式(yyyymmdd)。 在 SQL 语句中使用参数绑定来防止 SQL 注入。

示例(基于您的代码):

...

$id = 2;
$from = '20200301';
$to = '20200501';

$products = DB::select("
    SELECT DISTINCT
        products.PRODUCT_ID,
        products.PRODUCT_NAME,
        TRANSACTIONS_DTL.PRODUCT_ID,
        TRANSACTIONS_DTL.TRANS_ID,
        TRANSACTIONS_DTL.PRODUCT_VALUE,
        TRANSACTIONS_HD.TRANS_ID,
        TRANSACTIONS_HD.TRANS_DATE
    FROM products
    INNER JOIN TRANSACTIONS_DTL ON products.PRODUCT_ID = TRANSACTIONS_DTL.PRODUCT_ID
    INNER JOIN TRANSACTIONS_HD ON TRANSACTIONS_DTL.TRANS_ID = TRANSACTIONS_HD.TRANS_ID
    WHERE 
        (products.PRODUCT_ID = ?) AND 
        (CONVERT(date, TRANSACTIONS_HD.TRANS_DATE, 105) > CONVERT(date, ?)) AND 
        (CONVERT(date, TRANSACTIONS_HD.TRANS_DATE, 105) < CONVERT(date, ?))
", [$id, $from, $to]);

...

【讨论】:

【参考方案2】:

好的,在重新阅读本文时,您似乎需要这样做:

AND CAST(SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 7, 4)
        + SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 4, 2)
        + SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 1, 2) 
        + SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 12, 5)
        + ':00' AS datetime2) > '$from'
AND CAST(SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 7, 4)
        + SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 4, 2)
        + SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 1, 2) 
        + SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 12, 5)
        + ':00' AS datetime2) < '$to'

希望这更简单。 (为表使用别名会使其不那么密集)

在 SQL Server 中,请注意您的 $from 和 $to 应该只是格式为 'YYYYMMDD' 的字符串,例如'20201231'。无论使用哪种日期数据类型,无论语言和区域设置如何,这都将起作用。您只需将它们指定为字符串,无需强制转换。

注意:我还假设您表中的日期格式是 DD-MM-YYYY,因为我无法从您的示例中判断它们是哪种方式。如果您的本地日期格式是 MM-DD-YYYY(即美国日期),请改用此代码:

AND CAST(SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 7, 4)
        + SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 1, 2)
        + SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 4, 2) 
        + SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 12, 5)
        + ':00' AS datetime2) > '$from'
AND CAST(SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 7, 4)
        + SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 1, 2)
        + SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 4, 2) 
        + SUBSTRING(TRANSACTIONS_HD.TRANS_DATE), 12, 5)
        + ':00' AS datetime2) < '$to'

【讨论】:

我尝试了以下方法但没有成功:AND CAST(TRANSACTIONS_HD.TRANS_DATE + ':00' AS date) > CAST('$from' + ':00' AS date) 我只尝试使用“大于”日期,如果它工作不正常,现在就简单了,包括“小于” 您不需要将 ':00' 添加到 $from 和 $to 因为它们已经是日期值,并且它们也不需要强制转换。此外,在 SQL Server 中,您应该将日期发送为 'YYYYMMDD' 并避免使用任何其他格式。 (注意没有破折号或斜线)。这是唯一适用于所有日期数据类型以及所有区域和语言设置的安全日期格式。我猜你需要的更像是:

以上是关于在 PHP Laravel 中的 SQL Server 中将字符串转换为日期数据类型的主要内容,如果未能解决你的问题,请参考以下文章

PHP安全三板斧:过滤篇Laravel底层SQL注入规避

ubuntu + lamp + laravel 环境配置

将 PHP SQL 转换为 Laravel 查询构建器 [重复]

php laravel artisan 迁移模型中的错误?

SQL 到 JSON,ORM 用于 PHP 7 和 Laravel

laravel5.5探究容器的秘密