【问题标题】:Laravel binding parameter using insert() with convert() insideLaravel 使用 insert() 和 convert() 绑定参数
【发布时间】:2020-11-04 03:27:57
【问题描述】:

我很难绑定我的 SQL 查询,我只剩下几个脑细胞。

基本上,这段代码可以工作,但容易发生 SQL 注入:

return DB::connection('sqlsrv_rfo_user')
    ->table('dbo.tbl_rfaccount')
    ->insert([
        'Email' => $email,
        'id' => DB::raw("CONVERT(binary, '$username')"),
        'password' => DB::raw("CONVERT(binary, '$password')"),
        'birthdate' => $birthday,
        'accounttype' => 0,
        'BCodeTU' => 1
    ]);

我想弄清楚如何绑定这些代码行:

'id' => DB::raw("CONVERT(binary, '$username')"),
'password' => DB::raw("CONVERT(binary, '$password')"),

我确实尝试过:

'id' => DB::raw("CONVERT(binary, ?)", [$username]),
'password' => DB::raw("CONVERT(binary, ?)", [$password]),

得到了这个错误:

SQLSTATE[07002]: [Microsoft][ODBC Driver 13 for SQL Server]COUNT field incorrect or syntax error (SQL: insert into [dbo].[tbl_rfaccount] ([Email], [id], [password], [birthdate], [accounttype], [BCodeTU]) values (user@example.com, CONVERT(binary, 2011-11-11 00:00:00), CONVERT(binary, 0), 1, ?, ?))

还有这个:

'id' => DB::raw("CONVERT(binary, :username)", ['username' => $username]),
'password' => DB::raw("CONVERT(binary, :password)", ['password' => $password]),

得到了这个错误:

SQLSTATE[IMSSP]: An error occurred substituting the named parameters. (SQL: insert into [dbo].[tbl_rfaccount] ([Email], [id], [password], [birthdate], [accounttype], [BCodeTU]) values (user@example.com, CONVERT(binary, :username), CONVERT(binary, :password), 2011-11-11 00:00:00, 0, 1))

如果我尝试完整的原始:

return DB::connection('sqlsrv_rfo_user')
        ->insert("
        INSERT INTO [dbo].[tbl_rfaccount]
            ([id]
            ,[password]
            ,[accounttype]
            ,[birthdate]
            ,[BCodeTU]
            ,[Email])
        VALUES
        ((CONVERT(binary, ?)), (CONVERT(binary, ?)), ?, ?, ?, ?)
    ", [$username, $password, 0, $birthday, 1, $email]);

我收到此错误:

SQLSTATE[22001]: [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]String or binary data would be truncated. (SQL: INSERT INTO [dbo].[tbl_rfaccount] ([id] ,[password] ,[accounttype] ,[birthdate] ,[BCodeTU] ,[Email]) VALUES ((CONVERT(binary, user01)), (CONVERT(binary, password01)), 0, 2011-11-11 00:00:00, 1, user@example.com)

我从开始学习 Laravel 开始就一直在使用 Eloquent,但是我有一个项目迫使我使用这些编码方式,所以我别无选择。

【问题讨论】:

  • 第一次尝试是正确的,除了数组需要在问号之外。 DB::raw("CONVERT(binary, ?)", [$username])
  • @aynber 是的,抱歉,这只是一个错字,我现在要编辑问题,这正是我的代码的真实样子,但仍然无法正常工作。
  • 数据似乎存在一些问题。对于 ID,您似乎在传递 CONVERT(binary, 2011-11-11 00:00:00),密码是 CONVERT(binary, 0)
  • 我实际上试图弄清楚为什么会发生这种情况仍然找不到正确的方法。
  • 很公平,所以它是 varchar... 但 varchar 的长度是多少? create table tbl_refaccount (id varchar(what goes here?), ...)。我们确实需要查看tbl_rfaccount 的表定义,即列数据类型。

标签: php sql sql-server laravel sqlsrv


【解决方案1】:

根据您的最后一条错误消息,当您尝试完整的原始查询时:

SQLSTATE[22001]:[Microsoft][ODBC Driver 13 for SQL Server][SQL 服务器]字符串或二进制数据将被截断。 (SQL:插入 [dbo].[tbl_rfaccount] ([id] ,[password] ,[accounttype] ,[birthdate] ,[BCodeTU] ,[Email]) 值 ((CONVERT(binary, user01)), (CONVERT(binary, password01)), 0, 2011-11-11 00:00:00, 1, user@example.com)

您需要在CONVERT函数中指定字段的长度。

不是CONVERT(binary, user01),而是CONVERT(binary(16), user01)。指定与目标表中定义的列相同的长度。

如果不指定长度,则在某些情况下假定为 1,在某些情况下假定为 30。

Aaron Bertrand 写了一篇关于这个(和其他)坏习惯的详细文章: Bad habits to kick : declaring VARCHAR without (length)varcharbinaryvarbinary 与此处类似。

正如@Zhorov 在评论中正确指出的那样,CONVERT 函数假定长度为 30(如果未指定)。

-- CONVERT Syntax:  
CONVERT ( data_type [ ( length ) ] , expression [ , style ] )

...

长度

一个可选的整数,指定目标的长度 数据类型,用于允许用户指定长度的数据类型。这 默认值为 30。

这里有一个简单的例子来说明发生了什么:

SELECT
    CONVERT(binary(16), '1234567890123456') AS Bin16
    ,CONVERT(binary, '1234567890123456') as BinNoLength
;

结果:

+------------------------------------+----------------------------------------------------------------+
| Bin16                              | BinNoLength                                                    |
+------------------------------------+----------------------------------------------------------------+
| 0x31323334353637383930313233343536 | 0x313233343536373839303132333435360000000000000000000000000000 |
+------------------------------------+----------------------------------------------------------------+

所以,当您没有在CONVERT 中指定长度时,您将得到binary(30) 结果。

当您尝试将此 long 值插入到表中的列中时,您的列的长度不足以存储它,因此 long 值被截断,您会看到此错误消息。

【讨论】:

  • documentation 声明,对于允许用户指定长度的数据类型,length 是指定目标数据类型长度的可选整数 并且 默认值为 30。但是指定长度是一个好习惯。
  • 这个答案确实有效(我实际上将它从二进制(16)设置为二进制(13)顺便说一句),但我还有一个问题。使用该方法插入的数据与正确的不同,我得到了这个(屏幕截图):imgur.com/a/b1HoxHU,该屏幕截图中列出的所有帐户都有效,除了 ID 为asdasd0 和密码asdasd0 的行。使用您提供的答案插入 ID 为 asdasd0 的行。
  • @Zhorov,谢谢。您对 CONVERT 函数的行为是正确的。我已经更新了答案。
  • @RonnelMartinez,对不起,当我看你的截图时,我不明白你遇到了什么问题。我建议您问另一个问题,该问题将专注于插入的数据不是您期望的特定问题。您需要提供代码和值的示例、表的定义、您的期望和实际得到的。
  • 不管怎样,谢谢你的回答。无论如何,这实际上解决了我的问题。
【解决方案2】:

你可以试试这个

return DB::connection('sqlsrv_rfo_user')
    ->table('dbo.tbl_rfaccount')
    ->insert([
        'Email' => $email,
        'id' => DB::raw(`CONVERT(binary,$username)`),
        'password' => DB::raw(`CONVERT(binary,$password)`),
        'birthdate' => $birthday,
        'accounttype' => 0,
        'BCodeTU' => 1
    ]);

【讨论】:

  • 不工作,我很确定我没有错过任何逗号或什么,但我收到此错误:` SQLSTATE[42000]: [Microsoft][ODBC Driver 13 for SQL Server][SQL服务器]',' 附近的语法不正确。 (SQL: 插入 [dbo].[tbl_rfaccount] ([Email], [id], [password], [birthdate], [accounttype], [BCodeTU]) 值 ('example@example.com', , , ' 2011-11-11 00:00:00', 0, 1)) `
  • 首先使用consoling检查你的$username和$password
  • 我刚刚做到了。 $username$passwordDB::raw() 之前都有值
  • 然后使用 DB::raw(CONVERT($username USING BINARY))
  • 我得到:SQLSTATE[42000]: [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]'exampleUsername' 附近的语法不正确。 (SQL: 插入 [dbo].[tbl_rfaccount] ([Email], [id], [password], [birthdate], [accounttype], [BCodeTU]) 值 (example@outlook.com, CONVERT('exampleUsername' USING BINARY), CONVERT('exampleUsername' USING BINARY), 1900-01-01 00:00:00, 0, 1))
猜你喜欢
  • 2019-10-29
  • 2019-08-20
  • 1970-01-01
  • 2018-03-28
  • 1970-01-01
  • 2018-11-15
  • 2018-08-11
  • 2020-04-27
  • 2021-01-11
相关资源
最近更新 更多