programing

쿼리 빌더가 원시 SQL 쿼리를 문자열로 출력하려면 어떻게 해야 합니까?

minecode 2022. 10. 31. 21:28
반응형

쿼리 빌더가 원시 SQL 쿼리를 문자열로 출력하려면 어떻게 해야 합니까?

다음 코드가 지정됩니다.

DB::table('users')->get();

위의 데이터베이스 쿼리 작성기에서 생성할 원시 SQL 쿼리 문자열을 가져오고 싶습니다.이 예에서는 다음과 같습니다.SELECT * FROM users.

이거 어떻게 해?

하다를 사용하세요.toSql()QueryBuilder★★★★★★ 。

DB::table('users')->toSql()★★★★

"users"에서 *를 선택합니다.

이것은 이벤트청취자를 연결하는 것보다 쉽고, 작성하는 동안 어떤 시점에서 쿼리가 실제로 어떻게 표시되는지 확인할 수 있습니다.

이 빌더 할 수 있습니다.단, 이 메서드는 쿼리 빌더 및 웅변술에 사용할 수 있습니다.toSql().first() ★★★★★★★★★★★★★★★★★」get()이 방법을 사용하면 쿼리를 실행하는 동시에 SQL을 가져올 수 없습니다.

마지막으로 실행된 쿼리를 화면에 출력하려면 다음을 사용합니다.

\DB::enableQueryLog(); // Enable query log

// Your Eloquent query executed by using get()

dd(\DB::getQueryLog()); // Show results of log

가장 최근의 쿼리는 배열의 맨 아래에 있을 것입니다.

다음과 같은 일이 발생합니다.

array(1) {
  [0]=>
  array(3) {
    ["query"]=>
    string(21) "select * from "users""
    ["bindings"]=>
    array(0) {
    }
    ["time"]=>
    string(4) "0.92"
  }
}

(아래 조슈아 댓글 덕분에)

DB::QueryLog()는 쿼리를 합니다.$builder->get().

하기 전 하지 않고 를 할 수 .$builder->toSql()★★★★★★ 。

원시 SQL을 가져와 '?'를 실제 바인딩 값으로 바꾸는 예:

$query = str_replace(array('?'), array('\'%s\''), $builder->toSql());
$query = vsprintf($query, $builder->getBindings());
dump($query);

$result = $builder->get();

또는 존재하지 않는 테이블 또는 열을 사용하여 의도적으로 오류를 트리거할 수 있습니다.그런 다음 예외 메시지에서 생성된 쿼리를 볼 수 있습니다.

당신은 'luminate'를 들을 수 있습니다.query' 이벤트입니다.쿼리가 다음 이벤트청취자를 추가하기 전에

Event::listen('illuminate.query', function($query, $params, $time, $conn) 
{ 
    dd(array($query, $params, $time, $conn));
});

DB::table('users')->get();

다음과 같이 인쇄됩니다.

array(4) {
  [0]=>
  string(21) "select * from "users""
  [1]=>
  array(0) {
  }
  [2]=>
  string(4) "0.94"
  [3]=>
  string(6) "sqlite"
}

Larabel을 사용하지 않고 Illuminate를 사용하여 로그를 가져오려는 경우:

\Illuminate\Database\Capsule\Manager::getQueryLog();

다음과 같은 빠른 기능을 사용할 수도 있습니다.

function logger()
{
    $queries = \Illuminate\Database\Capsule\Manager::getQueryLog();
    $formattedQueries = [];
    foreach ($queries as $query) :
        $prep = $query['query'];

        foreach ($query['bindings'] as $binding) :

            if (is_bool($binding)) {
                $val = $binding === true ? 'TRUE' : 'FALSE';
            } else if (is_numeric($binding)) {
                $val = $binding;
            } else {
                $val = "'$binding'";
            }

            $prep = preg_replace("#\?#", $val, $prep, 1);
        endforeach;
        $formattedQueries[] = $prep;
    endforeach;
    return $formattedQueries;
}

편집

업데이트된 버전은 기본적으로 쿼리 로깅이 비활성화되어 있는 것 같습니다(위의 경우 빈 배열이 반환됩니다).할 때 켜려면 를 합니다.enableQueryLog

$capsule::connection()->enableQueryLog();

다시 편집

실제 질문을 고려했을 때 이전 모든 쿼리가 아닌 현재 단일 쿼리를 변환하기 위해 실제로 다음을 수행할 수 있습니다.

$sql = $query->toSql();
$bindings = $query->getBindings();

웅변에는 쿼리 문자열을 가져오는 방법이 있습니다.

toSql()

저희 같은 경우에는

 DB::table('users')->toSql(); 

돌아가다

select * from users

는 SQL 쿼리 문자열을 반환하는 정확한 솔루션입니다.이게 도움이 되길...

$data = User::toSql();
echo $data; //this will retrun select * from users. //here User is model

이것이 웅변적인 마지막 쿼리 또는 최종 쿼리를 디버깅하기 위해 제안할 수 있는 가장 좋은 해결책입니다.단, 이것도 설명했습니다.

// query builder
$query = DB::table('table_name')->where('id', 1);

// binding replaced
$sql = str_replace_array('?', $query->getBindings(), $query->toSql());

// for laravel 5.8^
$sql = Str::replaceArray('?', $query->getBindings(), $query->toSql());

// print
dd($sql);

larabel 5.1과 MySQL을 사용하면 내가 만든 다음 기능을 사용할 수 있습니다.

/*
 *  returns SQL with values in it
 */
function getSql($model)
{
    $replace = function ($sql, $bindings)
    {
        $needle = '?';
        foreach ($bindings as $replace){
            $pos = strpos($sql, $needle);
            if ($pos !== false) {
                if (gettype($replace) === "string") {
                     $replace = ' "'.addslashes($replace).'" ';
                }
                $sql = substr_replace($sql, $replace, $pos, strlen($needle));
            }
        }
        return $sql;
    };
    $sql = $replace($model->toSql(), $model->getBindings());
    
    return $sql;
}

입력 매개 변수로 다음 중 하나를 사용할 수 있습니다.

조명\데이터베이스\웅변가\빌더

조명\데이터베이스\웅변\관계\하스매니

조명\데이터베이스\쿼리\빌더

먼저 다음을 호출하여 쿼리 로그를 활성화해야 합니다.

DB::enableQueryLog();

DB 파사드를 사용하여 질의한 후 다음을 작성할 수 있습니다.

dd(DB::getQueryLog());

출력은 다음과 같습니다.

array:1 [▼
  0 => array:3 [▼
    "query" => "select * from `users` left join `website_user` on `users`.`id` = `website_user`.`user_id` left join `region_user` on `users`.`id` = `region_user`.`user_id` left ▶"
    "bindings" => array:5 [▶]
    "time" => 3.79
  ]
]

바인딩과 함께 SQL 쿼리를 가져오기 위한 '매크로 가능' 대체입니다.

  1. 메서드에boot() 아래 매크로 함수를 추가합니다.

    \Illuminate\Database\Query\Builder::macro('toRawSql', function(){
        return array_reduce($this->getBindings(), function($sql, $binding){
            return preg_replace('/\?/', is_numeric($binding) ? $binding : "'".$binding."'" , $sql, 1);
        }, $this->toSql());
    });
    
  2. 웅변가 빌더의 별칭을 추가합니다(Larabel 5.4+).

    \Illuminate\Database\Eloquent\Builder::macro('toRawSql', function(){
        return ($this->getQuery()->toRawSql());
    });
    
  3. 그런 다음 평소대로 디버깅합니다.(Larabel 5.4+)

    예: 쿼리 작성기

    \Log::debug(\DB::table('users')->limit(1)->toRawSql())
    

    예: 웅변가 빌더

    \Log::debug(\App\User::limit(1)->toRawSql());
    

5.부터 5까지, Larabel 5.1을 하지 않기 에, Alustic Builder는 Larabel 5.1을 사용하지 않습니다.Macroable,할 수 , " " "toRawSql을 얻으려면 .아래 예에 따라 동일한 결과를 얻으십시오.

예: 웅변가(Larabel 5.1~5.3)

\Log::debug(\App\User::limit(1)->getQuery()->toRawSql());

Larabel 5.8.15 현재 쿼리 빌더는 dd ★★★★★★★★★★★★★★★★★」dump 수 방법

DB::table('data')->where('a', 1)->dump();

첫 번째 방법:

단순히 방법을 사용하여 다음 작업을 수행할 수 있습니다.

$query = DB::table('users')->get();

echo $query->toSql();

정상적으로 동작하지 않는 경우는, 라라벨의 메뉴얼로부터 셋업 할 수 있습니다.

두 번째 방법:

또 다른 방법은

DB::getQueryLog()

그러나 빈 어레이가 반환되면 기본적으로는 비활성화되어 있습니다.

just enable with 을 유효하게 하다DB::enableQueryLog()그리고 그것은 뭔가요?

자세한 내용은 Github Issue를 참조하십시오.

도움이 되었으면 좋겠다:)

가장 쉬운 방법은 고의로 실수를 하는 것이다.예를 들어 다음과 같은 관계에 대한 전체 SQL 쿼리를 표시하려고 합니다.

 public function jobs()
        {
            return $this->belongsToMany(Job::class, 'eqtype_jobs')
                   ->withPivot(['created_at','updated_at','id'])
                   ->orderBy('pivot_created_at','desc');
        }

찾을 수 있는 열을 만들기 위해 을 는 들 해 기 위 택 i just to선, found다 to i be not니,합 a make here만열찾없여서수기 choose column을created_at and I changed it to 그래서 제가 그걸 바꿨어요.created_ats by adding trailing 후행 추가에 의해s…할 수 있다.

public function jobs()
            {
                return $this->belongsToMany(Job::class, 'eqtype_jobs')
                       ->withPivot(['created_ats','updated_at','id'])
                       ->orderBy('pivot_created_at','desc');
            }

따라서 디버거는 다음 오류를 반환합니다.

(4/4) 오류Ex 예외 SQL 상태: (42S22S22S22] 오류Ex 예외 SQL 상태: (42S22S22S22] 오류Ex 예외 SQL 상태:열(SQL_jq 유형_jq 유형_jq 유형_SQL 드 을 목 록)을 선택합니다.jobs.*, .*, .*,eqtype_jobs....set_id as ~하듯이pivot_set_id, , ,eqtype_jobs....job_id as ~하듯이pivot_job_id, , ,eqtype_jobs....created_ats as ~하듯이pivot_created_ats, , ,eqtype_jobs....updated_at as ~하듯이pivot_updated_at, , ,eqtype_jobs....id as ~하듯이pivot_id부에서jobs inner join 이너 조인트eqtype_jobs on 에jobs....id = = =eqtype_jobs....job_id어 어디 있죠?eqtype_jobs....set_id = = 56 주 56 μmpivot_created_at 0) ( /factoryshowdesc limit 20 offset 0) (: / home/said/said/wwwwwwwww/fp)

위의 오류 메시지는 오류와 함께 전체 SQL 쿼리를 반환합니다.

SQL: select  jobs.*, eqtype_jobs.set_id as pivot_set_id,  eqtype_jobs.job_id as pivot_job_id, eqtype_jobs.created_ats as pivot_created_ats, eqtype_jobs.updated_at as  pivot_updated_at, eqtype_jobs.id as pivot_id from jobs inner join eqtype_jobs on jobs.id = eqtype_jobs.job_id where  eqtype_jobs.set_id = 56 order by pivot_created_at desc limit 20 offset 0

여분의, 제, 이, 이, 이, 이, remove, remove, remove, remove, remove, remove, remove, nows에서 이 예: editor!created_at)에서합니다.

주의:

이 솔루션은 Larabel 5.4에서 테스트되었습니다.

초보자로서 이것이 최선의 접근법이라고 생각합니다.

echo "<pre>";
print_r($query->toSql());
print_r($query->getBindings());

이것 또한 여기에 묘사되어 있다.https://stackoverflow.com/a/59207557/9573341

이 기능을 응용 프로그램에 추가하고 전화를 걸기만 하면 됩니다.

function getQuery($sql){
        $query = str_replace(array('?'), array('\'%s\''), $sql->toSql());
        $query = vsprintf($query, $sql->getBindings());     
        return $query;
}

출력: "select * from"user어디에lang= 'en' 및status= '1' 주문 기준updated_atdesc limit 25 오프셋 0"

이미 답변된 많은 정보가 있습니다. SQL 쿼리를 실행하기 전에 출력해야 할 때마다 사용하던 결과를 게시합니다.

아래 샘플에 대해 생각해 보십시오.

$user = DB::table('user')->where('id',1);
echo $user->toSql();

echo $user -> toSql() = raw 쿼리는 출력될 뿐 전달된 파라미터는 표시되지 않습니다.

전달된 파라미터를 사용하여 쿼리를 출력하려면 다음과 같이 laravel getBindings() 및 helper str_replace_array를 사용합니다.

$queryWithParam = str_replace_array('?',$user->getBindings(),$user->toSql());
echo $queryWithParam;

이것 또한 도움이 되길 바랍니다.

debugbar 패키지 사용

composer require "barryvdh/laravel-debugbar": "2.3.*"

enter image description here

라라벨에서5.2그 이후로는요.사용할 수 있습니다.DB::listen실행 쿼리를 가져옵니다.

DB::listen(function ($query) {
    // $query->sql
    // $query->bindings
    // $query->time
});

또는 싱글을 디버깅하고 싶은 경우Builder인스턴스(instance)를 사용할 수 있습니다.toSql방법.

DB::table('posts')->toSql(); 

Larabel 실행 쿼리를 보려면 Larabel 쿼리 로그를 사용하십시오.

DB::enableQueryLog();

$queries = DB::getQueryLog();

이것은 기본 모델 클래스에 배치한 함수입니다.쿼리 빌더 객체를 전달하기만 하면 SQL 문자열이 반환됩니다.

function getSQL($builder) {
  $sql = $builder->toSql();
  foreach ( $builder->getBindings() as $binding ) {
    $value = is_numeric($binding) ? $binding : "'".$binding."'";
    $sql = preg_replace('/\?/', $value, $sql, 1);
  }
  return $sql;
}

가장 쉬운 방법인 toSql 메서드를 사용할 수 있습니다.

DB::table('users')->toSql();

또한 쿼리에 바인딩이 있고 바인딩이 있는 쿼리를 표시하려는 경우에도 마찬가지입니다.다음과 같은 것은 사용할 수 없습니다.

$query = DB::table('table')->whereIn('some_field', [1,2,30]); 

$sql_with_bindings = str_replace_array('?', $query->getBindings(), $query->toSql());

dd($sql_with_bindings);

이것을 시험해 보세요.

$results = DB::table('users')->toSql();
dd($results);

주의: get()은 원시 SQL 쿼리를 표시하기 위해 toSql()로 대체되었습니다.

라라벨 5.5용.x

응용 프로그램에서 실행되는 각 SQL 쿼리를 수신하려면 listen 메서드를 사용할 수 있습니다.이 방법은 쿼리 로깅 또는 디버깅에 유용합니다.쿼리 리스너를 서비스 프로바이더에 등록할 수 있습니다.

<?php

namespace App\Providers;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        DB::listen(function ($query) {
            // $query->sql
            // $query->bindings
            // $query->time
        });
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

원천

나는 이 틀을 좋아하지만, 그것이 쓰레기처럼 행동하는 것은 싫다.

DB::enableQueryLog()전혀 쓸모가 없다. DB::listen똑같이 쓸모없다.내가 말했을 때 질문의 일부를 보여줬어$query->count()하지만 만약 내가 한다면$query->get()할 말이 없습니다.

일관되게 기능하는 유일한 솔루션은 존재하지 않는 열/테이블 이름 등의 ORM 파라미터에 의도적으로 구문 또는 기타 오류를 삽입하여 디버깅모드일 때 명령줄에서 코드를 실행하는 것입니다.이것에 의해 최종적으로 완전한 frickin' 쿼리에서 SQL 오류가 발생합니다.그렇지 않으면 웹 서버에서 실행한 경우 로그 파일에 오류가 나타나기를 바랍니다.

실행된 모든 쿼리를 기록하려면 DB::enable을 사용합니다.QueryLog() icw DB::getQueryLog().출력의 구조는 다음과 같습니다.

[
  [
    "query" => "select * from "users" where name = ?"
    "bindings" => ["John Doe"]
    "time" => 0.34
  ],
  ...
]

또한 SQL과 컴파일된 바인딩을 해석하는 완벽한 함수를 얻기 위해 여기에 몇 가지 답변을 조합했습니다.이하를 참조해 주세요.이 기능을 구현하는 커스텀 빌더 클래스도 만들었습니다.사용자: where('name', John Doe')-> parse();

function parse_sql(string $sql, array $bindings) : string
{
  $compiled_bindings  = array_map('compile_binding', $bindings);

  return preg_replace_array("/\?/", $compiled_bindings, $sql);
}

function compile_binding($binding)
{
  $grammar = new MySqlGrammar;

  if (is_bool($binding))
  {
    return (int)$binding; //This line depends on the database implementation
  }

  if(is_string($binding))
  {
    return "'$binding'";
  }

  if ($binding instanceof DateTimeInterface)
  {
    return $binding->format($grammar->getDateFormat());
  }

  return $binding;
}

이 패키지를 사용하여 페이지를 로드할 때 실행 중인 모든 쿼리를 가져올 수 있습니다.

https://github.com/barryvdh/laravel-debugbar

마지막 쿼리 인쇄

DB::enableQueryLog();

$query        = DB::getQueryLog();
$lastQuery    = end($query);
print_r($lastQuery);

tinker를 사용하여 SQL 쿼리를 로그하려면 다음을 수행합니다.

$ php artisan tinker
Psy Shell v0.9.9 (PHP 7.3.5 — cli) by Justin Hileman
>>> DB::listen(function ($query) { dump($query->sql); dump($query->bindings); dump($query->time); });
=> null
>>> App\User::find(1)
"select * from `users` where `users`.`id` = ? limit 1"
array:1 [
  0 => 1
]
6.99
=> App\User {#3131
     id: 1,
     name: "admin",
     email: "admin@example.com",
     created_at: "2019-01-11 19:06:23",
     updated_at: "2019-01-11 19:06:23",
   }
>>>

뷰에 파일을.app/Providers/AppServiceProvider.php:

  1. 를 에 추가합니다.app/Providers/AppServiceProvider.php
/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    //
    DB::listen(function ($query) {
        $querySql = str_replace(['?'], ['\'%s\''], $query->sql);
        $queryRawSql = vsprintf($querySql, $query->bindings);
        Log::debug('[SQL EXEC]', [
                "raw sql"  => $queryRawSql,
                "time" => $query->time,
            ]
        );
    });
}
  1. 내 SQL 핸들 코드:
$users = DB::table('users')
    ->select(DB::raw('count(*) as user_count, username '))
    ->where('uid', '>=', 10)
    ->limit(100)
    ->groupBy('username')
    ->get()
;
dd($users);
  1. 「」storage/logs/laravel-2019-10-27.log:
[2019-10-27 17:39:17] local.DEBUG: [SQL EXEC] {"raw sql":"select count(*) as user_count, username  from `users` where `uid` >= '10' group by `username` limit 100","time":304.21} 

언급URL : https://stackoverflow.com/questions/18236294/how-do-i-get-the-query-builder-to-output-its-raw-sql-query-as-a-string

반응형