Laravel параметр привязки с использованием insert () с convert () внутри - PullRequest
5 голосов
/ 14 июля 2020

Мне сложно привязать мой 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))

И если я попробую полный raw:

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]);

Я получаю это error:

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)

Я использую Eloquent с тех пор, как начал изучать Laravel, но у меня есть проект, который заставляет меня использовать этот способ кодирования, поэтому у меня нет выбора.

Ответы [ 2 ]

2 голосов
/ 18 июля 2020

На основе вашего последнего сообщения об ошибке, когда вы пытаетесь выполнить полный необработанный запрос:

SQLSTATE [22001]: [Microsoft] [ODB C Driver 13 для SQL Server] [ SQL Server] Строковые или двоичные данные будут усечены . (SQL: ВСТАВИТЬ В [dbo]. [Tbl_rfaccount] ([id], [пароль], [тип учетной записи], [дата рождения], [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.

Аарон Бертран написал подробную статью об этой (и других) вредных привычках: Отбрасывать вредные привычки: объявление VARCHAR без (length) . varchar или binary или varbinary здесь аналогичны.

Как правильно указал @Zhorov в комментарии, функция CONVERT предполагает, что длина равна 30, если она не указана .

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

...

длина

Необязательное целое число, указывающее длину целевого типа данных для данных тип s, которые позволяют заданную пользователем длину. Значение по умолчанию - 30.

Вот простой пример, демонстрирующий, что происходит:

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

Результат:

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

Итак, если вы не укажете длину в CONVERT, вы получите результат binary(30).

И когда вы попытаетесь вставить это длинное значение в столбец в своей таблице, ваш столбец не длинный достаточно, чтобы сохранить его, поэтому длинное значение обрезается, и вы видите это сообщение об ошибке.

1 голос
/ 17 июля 2020

можешь попробовать это

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
    ]);
...