최신판 |
당신의 편집 |
1번째 줄: |
1번째 줄: |
| ==개요== | | ==개요== |
| {{작성중}} | | {{목차숨김|3}} |
| [[분류: Laravel]]
| |
| ;<nowiki>Database: Query Builder</nowiki> | | ;<nowiki>Database: Query Builder</nowiki> |
| ;<nowiki>데이터: 쿼리 빌더</nowiki> | | ;<nowiki>데이터: 쿼리 빌더</nowiki> |
| https://laravel.com/docs/11.x/queries
| |
|
| |
|
| ==소개== | | ==소개== |
| Laravel의 데이터베이스 쿼리 빌더는 데이터베이스 쿼리를 생성하고 실행하기 위한 편리하고 유연한 인터페이스를 제공합니다. 이 빌더는 애플리케이션에서 대부분의 데이터베이스 작업을 수행하는 데 사용할 수 있으며, Laravel이 지원하는 모든 데이터베이스 시스템과 완벽하게 호환됩니다. | | Laravel의 데이터베이스 쿼리 빌더는 데이터베이스 쿼리를 생성하고 실행하기 위한 편리하고 유연한 인터페이스를 제공합니다. 이 빌더는 애플리케이션에서 대부분의 데이터베이스 작업을 수행하는 데 사용할 수 있으며, Laravel이 지원하는 모든 데이터베이스 시스템과 완벽하게 호환됩니다. |
|
| |
|
| Laravel 쿼리 빌더는 SQL 인젝션 공격으로부터 애플리케이션을 보호하기 위해 PDO 파라미터 바인딩을 사용합니다. 쿼리 빌더에 전달되는 문자열을 클리닝(clean)하거나 정화(sanitize)할 필요가 없습니다. | | Laravel 쿼리 빌더는 SQL 인젝션 공격으로부터 애플리케이션을 보호하기 위해 PDO 파라미터 바인딩을 사용합니다. 쿼리 빌더에 전달되는 문자열을 크리닝(clean)하거나 정화(sanitize)할 필요가 없습니다. |
|
| |
|
| PDO는 컬럼 이름 바인딩을 지원하지 않습니다. 따라서 사용자 입력이 쿼리에서 참조되는 컬럼 이름, 특히 "order by" 컬럼을 결정하도록 허용해서는 안 됩니다. | | PDO는 컬럼 이름 바인딩을 지원하지 않습니다. 따라서 사용자 입력이 쿼리에서 참조되는 컬럼 이름, 특히 "order by" 컬럼을 결정하도록 허용해서는 안 됩니다. |
|
| |
|
| ==데이터베이스 쿼리 실행== | | ==데이터베이스 쿼리 실행== |
| ;테이블에서 모든 행 조회
| | ====테이블에서 모든 행 조회==== |
| 다음은 <code>DB</code> 파사드에서 제공하는 <code>table</code> 메소드를 사용하여 쿼리를 시작하는 방법에 대한 설명입니다. <code>table</code> 메소드는 주어진 테이블에 대한 유창한 쿼리 빌더 인스턴스를 반환하며, 이를 통해 쿼리에 더 많은 제약조건을 연쇄적으로 추가하고, 마지막으로 <code>get</code> 메소드를 사용하여 쿼리 결과를 검색할 수 있습니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| <?php
| |
|
| |
| namespace App\Http\Controllers;
| |
|
| |
| use Illuminate\Support\Facades\DB;
| |
| use Illuminate\View\View;
| |
|
| |
| class UserController extends Controller
| |
| {
| |
| /**
| |
| * Show a list of all of the application's users.
| |
| */
| |
| public function index(): View
| |
| {
| |
| $users = DB::table('users')->get();
| |
|
| |
| return view('user.index', ['users' => $users]);
| |
| }
| |
| }
| |
| </syntaxhighlight>
| |
| | |
| <code>get</code> 메소드는 쿼리 결과를 포함하는 <code>Illuminate\Support\Collection</code> 인스턴스를 반환하며, 각 결과는 PHP의 <code>stdClass</code> 객체의 인스턴스입니다. 각 컬럼의 값은 객체의 속성으로 접근하여 가져올 수 있습니다.
| |
| | |
| <syntaxhighlight lang='php'>
| |
| use Illuminate\Support\Facades\DB;
| |
|
| |
| $users = DB::table('users')->get();
| |
|
| |
| foreach ($users as $user) {
| |
| echo $user->name;
| |
| }
| |
| </syntaxhighlight>
| |
| | |
| Laravel 컬렉션은 데이터를 매핑하고 축소하는 데 매우 강력한 다양한 메소드를 제공합니다. Laravel 콜렉션에 대한 자세한 내용은 콜렉션 문서를 참조하십시오.
| |
| | |
| ;테이블에서 단일 행 / 컬럼 조회
| |
| | |
| 데이터베이스 테이블에서 단일 행만 검색해야 하는 경우, <code>DB</code> 파사드의 <code>first</code> 메소드를 사용할 수 있습니다. 이 메소드는 단일 <code>stdClass</code> 객체를 반환합니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| $user = DB::table('users')->where('name', 'John')->first();
| |
|
| |
| return $user->email;
| |
| </syntaxhighlight>
| |
|
| |
|
| 전체 행이 필요하지 않다면, <code>value</code> 메소드를 사용하여 레코드에서 단일 값을 추출할 수 있습니다. 이 메소드는 해당 컬럼의 값을 직접 반환합니다:
| | ====테이블에서 단일 행 / 컬럼 조회==== |
|
| |
|
| <syntaxhighlight lang='php'>
| | ====컬럼 값 목록 조회==== |
| $email = DB::table('users')->where('name', 'John')->value('email');
| |
| </syntaxhighlight>
| |
| | |
| <code>id</code> 컬럼 값을 기준으로 단일 행을 검색하려면, <code>find</code> 메소드를 사용하세요:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| $user = DB::table('users')->find(3);
| |
| </syntaxhighlight>
| |
| | |
| ;컬럼 값 목록 조회
| |
| | |
| 단일 컬럼의 값을 포함하는 <code>Illuminate\Support\Collection</code> 인스턴스를 검색하려면 <code>pluck</code> 메소드를 사용할 수 있습니다. 이 예제에서는 사용자 타이틀의 콜렉션을 검색합니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| use Illuminate\Support\Facades\DB;
| |
|
| |
| $titles = DB::table('users')->pluck('title');
| |
|
| |
| foreach ($titles as $title) {
| |
| echo $title;
| |
| }
| |
| </syntaxhighlight>
| |
| | |
| 결과 콜렉션이 사용할 키를 지정하려면 <code>pluck</code> 메소드의 두 번째 인수로 지정할 수 있습니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| $titles = DB::table('users')->pluck('title', 'name');
| |
|
| |
| foreach ($titles as $name => $title) {
| |
| echo $title;
| |
| }
| |
| </syntaxhighlight>
| |
| | |
| ===결과 청킹===
| |
| 수천 개의 데이터베이스 레코드를 작업해야 하는 경우, <code>DB</code> 파사드에서 제공하는 <code>chunck</code> 메소드를 사용하는 것을 고려하십시오. 이 메소드는 한 번에 작은 청크의 결과를 가져와 각 청크를 처리할 클로저로 전달합니다. 예를 들어, 한 번에 100개의 레코드를 청크로 나누어 전체 사용자 테이블을 가져오는 방법은 다음과 같습니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| use Illuminate\Support\Collection;
| |
| use Illuminate\Support\Facades\DB;
| |
|
| |
| DB::table('users')->orderBy('id')->chunk(100, function (Collection $users) {
| |
| foreach ($users as $user) {
| |
| // ...
| |
| }
| |
| });
| |
| </syntaxhighlight>
| |
| | |
| 클로저에서 false를 반환하여 추가 청크 처리를 중단할 수 있습니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| DB::table('users')->orderBy('id')->chunk(100, function (Collection $users) {
| |
| // 레코드 처리...
| |
|
| |
| return false;
| |
| });
| |
| </syntaxhighlight>
| |
| | |
| 결과를 청크로 나누는 동안 데이터베이스 레코드를 업데이트하는 경우, 청크 결과가 예기치 않게 변경될 수 있습니다. 청크로 나눈 후 검색된 레코드를 업데이트할 계획이라면, 항상 <code>chunkById</code> 메소드를 사용하는 것이 좋습니다. 이 메소드는 레코드의 기본키를 기준으로 자동으로 결과를 페이지로 나눕니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| DB::table('users')->where('active', false)
| |
| ->chunkById(100, function (Collection $users) {
| |
| foreach ($users as $user) {
| |
| DB::table('users')
| |
| ->where('id', $user->id)
| |
| ->update(['active' => true]);
| |
| }
| |
| });
| |
| </syntaxhighlight>
| |
| | |
| 청크 콜백 내부에서 레코드를 업데이트하거나 삭제할 때, 기본키나 외래키에 대한 변경사항이 청크 쿼리에 영향을 줄 수 있습니다. 이로 인해 레코드가 청크 결과에 포함되지 않을 수 있습니다.
| |
| | |
| ===게으른(lazy) 결과 스트리밍===
| |
| <code>lazy</code> 메소드는 <code>chunk</code> 메소드와 유사하게 쿼리를 청크 단위로 실행합니다. 그러나 각 청크를 콜백으로 전달하는 대신, <code>lazy()</code> 메소드는 <code>LazyCollection</code>을 반환하여 결과를 단일 스트림으로 처리할 수 있게 합니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| use Illuminate\Support\Facades\DB;
| |
|
| |
| DB::table('users')->orderBy('id')->lazy()->each(function (object $user) {
| |
| // ...
| |
| });
| |
| </syntaxhighlight>
| |
| | |
| 마찬가지로, 검색된 레코드를 반복하면서 업데이트하려는 경우 <code>lazyById</code> 또는 <code>lazyByIdDesc</code> 메소드를 사용하는 것이 좋습니다. 이 메소드들은 레코드의 기본키를 기준으로 결과를 자동으로 페이지화합니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| DB::table('users')->where('active', false)
| |
| ->lazyById()->each(function (object $user) {
| |
| DB::table('users')
| |
| ->where('id', $user->id)
| |
| ->update(['active' => true]);
| |
| });
| |
| </syntaxhighlight>
| |
| | |
| 레코드를 반복하면서 업데이트하거나 삭제할 때, 기본 키 또는 외래 키에 대한 변경은 청크 쿼리에 영향을 미칠 수 있습니다. 이로 인해 레코드가 결과에 포함되지 않을 수 있습니다.
| |
|
| |
|
| | ===청킹 결과=== |
| | ===게으른 결과 스트리밍=== |
| ===집계=== | | ===집계=== |
| 쿼리 빌더는 <code>count</code>, <code>max</code>, <code>min</code>, <code>avg</code>, <code>sum</code>과 같은 집계 값을 조회하기 위한 다양한 메소드를 제공합니다. 쿼리를 작성한 후 이러한 메소드 중 하나를 호출할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| use Illuminate\Support\Facades\DB;
| |
|
| |
| $users = DB::table('users')->count();
| |
|
| |
| $price = DB::table('orders')->max('price');
| |
| </syntaxhighlight>
| |
|
| |
| 물론, 이러한 메소드를 다른 절과 결합하여 집계 값을 세밀하게 조정할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $price = DB::table('orders')
| |
| ->where('finalized', 1)
| |
| ->avg('price');
| |
| </syntaxhighlight>
| |
|
| |
| ;레코드 존재 여부 확인
| |
| 쿼리의 제약 조건에 맞는 레코드가 존재하는지 확인하기 위해 <code>count</code> 메소드를 사용하는 대신, <code>exists</code>와 <code>doesntExist</code> 메소드를 사용할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| if (DB::table('orders')->where('finalized', 1)->exists()) {
| |
| // ...
| |
| }
| |
|
| |
| if (DB::table('orders')->where('finalized', 1)->doesntExist()) {
| |
| // ...
| |
| }
| |
| </syntaxhighlight>
| |
|
| |
| ==Select 문==
| |
| ;Select 절 지정하기
| |
| 데이터베이스 테이블에서 모든 컬럼을 선택하고 싶지 않을 때가 있습니다. <code>select</code> 메소드를 사용하여 쿼리에 대한 커스텀 "select" 절을 지정할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| use Illuminate\Support\Facades\DB;
| |
|
| |
| $users = DB::table('users')
| |
| ->select('name', 'email as user_email')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| <code>distinct</code> 메소드를 사용하면 쿼리가 고유한 결과를 반환하도록 강제할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')->distinct()->get();
| |
| </syntaxhighlight>
| |
|
| |
| 이미 쿼리 빌더 인스턴스를 가지고 있고 기존 select 절에 열을 추가하려면 <code>addSelect</code> 메소드를 사용할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $query = DB::table('users')->select('name');
| |
|
| |
| $users = $query->addSelect('age')->get();
| |
| </syntaxhighlight>
| |
|
| |
|
| | ==문 선택== |
| ==원시 표현== | | ==원시 표현== |
| 때로는 쿼리에 임의의 문자열을 삽입해야 할 때가 있습니다. 원시 문자열 표현을 만들기 위해서는 <code>DB</code> 파사드에서 제공하는 <code>raw</code> 메소드를 사용할 수 있습니다.
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->select(DB::raw('count(*) as user_count, status'))
| |
| ->where('status', '<>', 1)
| |
| ->groupBy('status')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| 원시 문은 문자열로 쿼리에 삽입되므로 SQL 인젝션 취약성을 피하기 위해 매우 신중해야 합니다.
| |
|
| |
| ;원시 메소드
| |
|
| |
| <code>DB::raw</code> 메소드 대신에 다양한 쿼리의 부분에 원시 표현식을 삽입하기 위해 다음 메소드들을 사용할 수 있습니다. '''원시 표현식을 사용하는 쿼리는 SQL 인젝션 취약성으로부터 보호되지 않을 수 있음을 유의하십시오.'''
| |
|
| |
| ;selectRaw
| |
|
| |
| <code>selectRaw</code> 메소드는 <code>addSelect(DB::raw(/* ... */))</code> 대신 사용할 수 있습니다. 이 메소드는 선택적으로 두 번째 인수로 바인딩 배열을 받습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $orders = DB::table('orders')
| |
| ->selectRaw('price * ? as price_with_tax', [1.0825])
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;where Raw / orWhereRaw
| |
|
| |
| <code>whereRaw</code>와 <code>orWhereRaw</code> 메소드는 쿼리에 원시 "where" 절을 삽입하는 데 사용됩니다. 이 메소드는 선택적으로 두 번째 인수로 바인딩 배열을 받습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $orders = DB::table('orders')
| |
| ->whereRaw('price > IF(state = "TX", ?, 100)', [200])
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;havingRaw / orHavingRaw
| |
|
| |
| <code>havingRaw</code>와 <code>orHavingRaw</code> 메소드는 "having" 절의 값으로 원시 문자열을 제공하는 데 사용됩니다. 이 메소드는 선택적으로 두 번째 인수로 바인딩 배열을 받습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $orders = DB::table('orders')
| |
| ->select('department', DB::raw('SUM(price) as total_sales'))
| |
| ->groupBy('department')
| |
| ->havingRaw('SUM(price) > ?', [2500])
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;orderByRaw
| |
|
| |
| <code>orderByRaw</code> 메소드는 "order by" 절의 값으로 원시 문자열을 제공하는 데 사용됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $orders = DB::table('orders')
| |
| ->orderByRaw('updated_at - created_at DESC')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;groupByRaw
| |
|
| |
| <code>groupByRaw</code> 메소드는 "group by" 절의 값으로 원시 문자열을 제공하는 데 사용됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $orders = DB::table('orders')
| |
| ->select('city', 'state')
| |
| ->groupByRaw('city, state')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ==조인== | | ==조인== |
| ;내부 조인(inner join) 절
| |
| 쿼리 빌더를 사용하여 쿼리에 조인 절을 추가할 수 있습니다. 기본적인 "내부 조인"을 수행하려면 쿼리 빌더 인스턴스의 <code>join</code> 메소드를 사용할 수 있습니다. <code>join</code> 메소드에 전달되는 첫 번째 인수는 조인할 테이블의 이름이며, 나머지 인수는 조인에 필요한 컬럼 제약조건을 지정합니다. 단일 쿼리에서 여러 테이블을 조인할 수도 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| use Illuminate\Support\Facades\DB;
| |
|
| |
| $users = DB::table('users')
| |
| ->join('contacts', 'users.id', '=', 'contacts.user_id')
| |
| ->join('orders', 'users.id', '=', 'orders.user_id')
| |
| ->select('users.*', 'contacts.phone', 'orders.price')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;왼쪽 조인(left join) / 오른쪽 조인(right join) 절
| |
| "내부 조인" 대신 "왼쪽 조인" 또는 "오른쪽 조인"을 수행하려면 <code>leftJoin</code> 또는 <code>rightJoin</code> 메소드를 사용하세요. 이 메소드의 시그니처는 <code>join</code> 메소드와 동일합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
| |
| ->get();
| |
|
| |
| $users = DB::table('users')
| |
| ->rightJoin('posts', 'users.id', '=', 'posts.user_id')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;교차 조인(cross join) 절
| |
| <code>crossJoin</code> 메소드를 사용하여 "교차 조인"을 수행할 수 있습니다. 교차 조인은 첫 번째 테이블과 조인된 테이블 간의 카티전 곱을 생성합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $sizes = DB::table('sizes')
| |
| ->crossJoin('colors')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;고급 조인 절
| |
| 더 고급 조인 절을 지정할 수도 있습니다. 시작하려면, <code>join</code> 메소드의 두 번째 인수로 클로저를 전달하세요. 클로저는 <code>Illuminate\Database\Query\JoinClause</code> 인스턴스를 수신하여 "조인" 절에 대한 제약조건을 지정할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| DB::table('users')
| |
| ->join('contacts', function (JoinClause $join) {
| |
| $join->on('users.id', '=', 'contacts.user_id')->orOn(/* ... */);
| |
| })
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| 조인에 "where" 절을 사용하려면 <code>JoinClause</code> 인스턴스에서 제공하는 <code>where</code>와 <code>orWhere</code> 메소드를 사용할 수 있습니다. 이 메소드들은 두 컬럼을 비교하는 대신 컬럼을 값과 비교합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| DB::table('users')
| |
| ->join('contacts', function (JoinClause $join) {
| |
| $join->on('users.id', '=', 'contacts.user_id')
| |
| ->where('contacts.user_id', '>', 5);
| |
| })
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;서브쿼리 조인
| |
| <code>joinSub</code>, <code>leftJoinSub</code>, <code>rightJoinSub</code> 메소드를 사용하여 쿼리를 서브쿼리에 조인할 수 있습니다. 이 메소드 각각은 서브쿼리, 테이블 별칭, 관련 컬럼을 정의하는 클로저를 세 인수로 받습니다. 이 예제에서는 각 사용자 레코드에 사용자의 가장 최근에 게시된 블로그 게시물의 <code>created_at</code> 타임스탬프도 포함된 사용자 콜렉션을 검색합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $latestPosts = DB::table('posts')
| |
| ->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))
| |
| ->where('is_published', true)
| |
| ->groupBy('user_id');
| |
|
| |
| $users = DB::table('users')
| |
| ->joinSub($latestPosts, 'latest_posts', function (JoinClause $join) {
| |
| $join->on('users.id', '=', 'latest_posts.user_id');
| |
| })->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;래터럴 조인(lateral join)
| |
| {{WARNING}}
| |
| 래터럴 조인은 현재 PostgreSQL, MySQL >= 8.0.14, SQL Server에서 지원됩니다.
| |
| {{/WARNING}}
| |
|
| |
| <code>joinLateral</code>, <code>leftJoinLateral</code> 메소드를 사용하여 서브쿼리와 "래터럴 조인"을 수행할 수 있습니다. 이 메소드 각각은 두 인수, 서브쿼리와 테이블 별칭을 받습니다. 조인 조건은 주어진 서브쿼리의 <code>where</code> 절 내에 지정해야 합니다. 래터럴 조인은 각 행에 대해 평가되며 서브쿼리 외부의 컬럼을 참조할 수 있습니다.
| |
|
| |
| 이 예제에서는 각 사용자와 사용자의 가장 최근의 블로그 게시물 세 개를 조회합니다. 각 사용자는 결과 집합에서 최대 세 개의 행을 생성할 수 있으며, 각 행은 사용자의 가장 최근 블로그 게시물에 해당합니다. 조인 조건은 현재 사용자 행을 참조하는 서브쿼리 내의 <code>whereColumn</code> 절로 지정됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $latestPosts = DB::table('posts')
| |
| ->select('id as post_id', 'title as post_title', 'created_at as post_created_at')
| |
| ->whereColumn('user_id', 'users.id')
| |
| ->orderBy('created_at', 'desc')
| |
| ->limit(3);
| |
|
| |
| $users = DB::table('users')
| |
| ->joinLateral($latestPosts, 'latest_posts')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ==유니온== | | ==유니온== |
| ==기본 Where 절== | | ==기본 Where 절== |
432번째 줄: |
73번째 줄: |
|
| |
|
| ===Or Where 절=== | | ===Or Where 절=== |
| Query Builder의 <code>where</code> 메소드를 연속으로 호출할 때, "where" 절들은 <code>and</code> 연산자로 결합됩니다. 그러나 <code>orWhere</code> 메소드를 사용하여 <code>or</code> 연산자로 절을 쿼리에 추가할 수 있습니다. <code>orWhere</code> 메소드는 <code>where</code> 메소드와 동일한 인수를 받습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->where('votes', '>', 100)
| |
| ->orWhere('name', 'John')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| 괄호 안에 "or" 조건을 그룹화해야 하는 경우, <code>orWhere</code> 메소드의 첫 번째 인수로 클로저를 전달할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->where('votes', '>', 100)
| |
| ->orWhere(function (Builder $query) {
| |
| $query->where('name', 'Abigail')
| |
| ->where('votes', '>', 50);
| |
| })
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| 위의 예제는 다음 SQL을 생성합니다:
| |
|
| |
| <syntaxhighlight lang='sql'>
| |
| select * from users where votes > 100 or (name = 'Abigail' and votes > 50)
| |
| </syntaxhighlight>
| |
|
| |
| 전역 스코프가 적용될 때 예기치 않은 동작을 방지하기 위해 항상 <code>orWhere</code> 호출을 그룹화해야 합니다.
| |
|
| |
| ===Where Not 절=== | | ===Where Not 절=== |
| <code>whereNot</code>과 <code>orWhereNot</code> 메소드는 주어진 그룹의 쿼리 제약 조건을 부정하는 데 사용할 수 있습니다. 예를 들어, 다음 쿼리는 클리어런스 중이거나 가격이 10보다 적은 제품을 제외합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $products = DB::table('products')
| |
| ->whereNot(function (Builder $query) {
| |
| $query->where('clearance', true)
| |
| ->orWhere('price', '<', 10);
| |
| })
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ===Where Any / All 절=== | | ===Where Any / All 절=== |
| 때로는 여러 컬럼에 동일한 쿼리 제약조건을 적용해야 할 때가 있습니다. 예를 들어, 주어진 목록의 모든 컬럼이 특정 값과 <code>LIKE</code> 조건에 맞는 모든 레코드를 조회하고 싶을 수 있습니다. 이를 위해 <code>whereAny</code> 메소드를 사용할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->where('active', true)
| |
| ->whereAny([
| |
| 'name',
| |
| 'email',
| |
| 'phone',
| |
| ], 'LIKE', 'Example%')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| 위의 쿼리는 다음 SQL로 변환됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| SELECT *
| |
| FROM users
| |
| WHERE active = true AND (
| |
| name LIKE 'Example%' OR
| |
| email LIKE 'Example%' OR
| |
| phone LIKE 'Example%'
| |
| )
| |
| </syntaxhighlight>
| |
|
| |
| 마찬가지로, <code>whereAll</code> 메소드를 사용하여 주어진 모든 컬럼이 특정 제약조건에 맞는 레코드를 조회할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $posts = DB::table('posts')
| |
| ->where('published', true)
| |
| ->whereAll([
| |
| 'title',
| |
| 'content',
| |
| ], 'LIKE', '%Laravel%')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| 위의 쿼리는 다음 SQL로 변환됩니다:
| |
|
| |
| <syntaxhighlight lang='sql'>
| |
| SELECT *
| |
| FROM posts
| |
| WHERE published = true AND (
| |
| title LIKE '%Laravel%' AND
| |
| content LIKE '%Laravel%'
| |
| )
| |
| </syntaxhighlight>
| |
|
| |
| ===JSON Where 절=== | | ===JSON Where 절=== |
| Laravel은 JSON 컬럼 유형을 지원하는 데이터베이스에서 JSON 컬럼 유형을 쿼리하는 것을 지원합니다. 현재 MySQL 8.0+, PostgreSQL 12.0+, SQL Server 2017+, SQLite 3.39.0+ ([https://www.sqlite.org/json1.html JSON1 확장] 포함)이 이에 해당합니다. JSON 컬럼을 쿼리하려면 <code>-></code> 연산자를 사용하세요:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->where('preferences->dining->meal', 'salad')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| JSON 배열을 쿼리하려면 <code>whereJsonContains</code>를 사용할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereJsonContains('options->languages', 'en')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| MySQL 또는 PostgreSQL 데이터베이스를 사용하는 경우, <code>whereJsonContains</code> 메소드에 값을 배열로 전달할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereJsonContains('options->languages', ['en', 'de'])
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| JSON 배열의 길이를 기준으로 쿼리하려면 <code>whereJsonLength</code> 메소드를 사용할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereJsonLength('options->languages', 0)
| |
| ->get();
| |
|
| |
| $users = DB::table('users')
| |
| ->whereJsonLength('options->languages', '>', 1)
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ===추가 Where 절=== | | ===추가 Where 절=== |
| ;whereBetween / orWhereBetween
| |
| <code>whereBetween</code> 메소드는 컬럼의 값이 두 값 사이에 있는지 확인합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereBetween('votes', [1, 100])
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;whereNotBetween / orWhereNotBetween
| |
| <code>whereNotBetween</code> 메소드는 컬럼의 값이 두 값 사이에 있지 않은지 확인합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereNotBetween('votes', [1, 100])
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;whereBetweenColumns / whereNotBetweenColumns / orWhereBetweenColumns / orWhereNotBetweenColumns
| |
| <code>whereBetweenColumns</code> 메소드는 같은 테이블 행에 있는 두 컬럼 값 사이에 있는지 확인합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $patients = DB::table('patients')
| |
| ->whereBetweenColumns('weight', ['minimum_allowed_weight', 'maximum_allowed_weight'])
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| <code>whereNotBetweenColumns</code> 메소드는 같은 테이블 행에 있는 두 컬럼 값 사이에 있지 않은지 확인합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $patients = DB::table('patients')
| |
| ->whereNotBetweenColumns('weight', ['minimum_allowed_weight', 'maximum_allowed_weight'])
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;whereIn / whereNotIn / orWhereIn / orWhereNotIn
| |
| <code>whereIn</code> 메소드는 주어진 컬럼의 값이 주어진 배열 내에 있는지 확인합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereIn('id', [1, 2, 3])
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| <code>whereNotIn</code> 메소드는 주어진 컬럼의 값이 주어진 배열 내에 없는지 확인합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereNotIn('id', [1, 2, 3])
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| <code>whereIn</code> 메소드의 두 번째 인자로 쿼리 객체를 제공할 수도 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $activeUsers = DB::table('users')->select('id')->where('is_active', 1);
| |
|
| |
| $users = DB::table('comments')
| |
| ->whereIn('user_id', $activeUsers)
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| 위의 예는 다음 SQL을 생성합니다:
| |
|
| |
| <syntaxhighlight lang='sql'>
| |
| select * from comments where user_id in (
| |
| select id
| |
| from users
| |
| where is_active = 1
| |
| )
| |
| </syntaxhighlight>
| |
|
| |
| {{WARNING}}
| |
| 대량의 정수 바인딩을 쿼리에 추가하는 경우, <code>whereIntegerInRaw</code> 또는 <code>whereIntegerNotInRaw</code> 메소드를 사용하여 메모리 사용량을 크게 줄일 수 있습니다.
| |
| {{/WARNING}}
| |
|
| |
| ;whereNull / whereNotNull / orWhereNull / orWhereNotNull
| |
| <code>whereNull</code> 메소드는 주어진 컬럼의 값이 NULL인지 확인합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereNull('updated_at')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| <code>whereNotNull</code> 메소드는 주어진 컬럼의 값이 NULL이 아닌지 확인합니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereNotNull('updated_at')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;whereDate / whereMonth / whereDay / whereYear / whereTime
| |
| <code>whereDate</code> 메소드는 컬럼의 값을 특정 날짜와 비교하는 데 사용됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereDate('created_at', '2016-12-31')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| <code>whereMonth</code> 메소드는 컬럼의 값을 특정 월과 비교하는 데 사용됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereMonth('created_at', '12')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| <code>whereDay</code> 메소드는 컬럼의 값을 특정 일과 비교하는 데 사용됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereDay('created_at', '31')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| <code>whereYear</code> 메소드는 컬럼의 값을 특정 연도와 비교하는 데 사용됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereYear('created_at', '2016')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| <code>whereTime</code> 메소드는 컬럼의 값을 특정 시간과 비교하는 데 사용됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereTime('created_at', '=', '11:20:45')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| ;whereColumn / orWhereColumn
| |
| <code>whereColumn</code> 메소드는 두 컬럼이 같은지 확인하는 데 사용됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereColumn('first_name', 'last_name')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| <code>whereColumn</code> 메소드에 비교 연산자를 전달할 수도 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereColumn('updated_at', '>', 'created_at')
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| 또한 <code>whereColumn</code> 메소드에 컬럼 비교 배열을 전달할 수도 있습니다. 이러한 조건은 <code>and</code> 연산자로 연결됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereColumn([
| |
| ['first_name', '=', 'last_name'],
| |
| ['updated_at', '>', 'created_at'],
| |
| ])->get();
| |
| </syntaxhighlight>
| |
|
| |
| ===논리적 그룹화=== | | ===논리적 그룹화=== |
| 쿼리의 원하는 논리적 그룹화를 달성하기 위해 여러 "where" 절을 괄호 안에 그룹화해야 할 때가 있습니다. 사실, 예상치 못한 쿼리 동작을 피하기 위해 <code>orWhere</code> 메소드 호출을 항상 괄호 안에 그룹화하는 것이 좋습니다. 이를 달성하기 위해, 클로저를 <code>where</code> 메소드에 전달할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->where('name', '=', 'John')
| |
| ->where(function (Builder $query) {
| |
| $query->where('votes', '>', 100)
| |
| ->orWhere('title', '=', 'Admin');
| |
| })
| |
| ->get();
| |
| </syntaxhighlight>
| |
|
| |
| 보시다시피, 클로저를 <code>where</code> 메소드에 전달하면 쿼리 빌더가 제약조건 그룹을 시작하도록 지시합니다. 클로저는 쿼리 빌더 인스턴스를 받게 되며, 이 인스턴스를 사용하여 괄호 그룹에 포함되어야 하는 제약 조건을 설정할 수 있습니다. 위의 예제는 다음과 같은 SQL을 생성합니다:
| |
|
| |
| <syntaxhighlight lang='sql'>
| |
| select * from users where name = 'John' and (votes > 100 or title = 'Admin')
| |
| </syntaxhighlight>
| |
|
| |
| {{WARNING}}
| |
| 글로벌 스코프가 적용될 때 예상치 못한 동작을 피하기 위해 항상 <code>orWhere</code> 호출을 그룹화해야 합니다.
| |
| {{/WARNING}}
| |
|
| |
| ==고급 Where 절== | | ==고급 Where 절== |
| ===Where Exists 절=== | | ===Where Exists 조항=== |
| <code>whereExists</code> 메소드는 "where exists" SQL 절을 작성할 수 있게 해줍니다. <code>whereExists</code> 메소드는 클로저를 인수로 받습니다. 이 클로저는 쿼리 빌더 인스턴스를 받게 되며, "exists" 절 내에 배치될 쿼리를 정의할 수 있게 합니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereExists(function (Builder $query) {
| |
| $query->select(DB::raw(1))
| |
| ->from('orders')
| |
| ->whereColumn('orders.user_id', 'users.id');
| |
| })
| |
| ->get();
| |
| </syntaxhighlight>
| |
| | |
| 또는, 클로저 대신 쿼리 객체를 <code>whereExists</code> 메소드에 제공할 수도 있습니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| $orders = DB::table('orders')
| |
| ->select(DB::raw(1))
| |
| ->whereColumn('orders.user_id', 'users.id');
| |
| | |
| $users = DB::table('users')
| |
| ->whereExists($orders)
| |
| ->get();
| |
| </syntaxhighlight>
| |
| | |
| 위의 두 예제는 모두 다음 SQL을 생성합니다:
| |
| | |
| <syntaxhighlight lang='sql'>
| |
| select * from users
| |
| where exists (
| |
| select 1
| |
| from orders
| |
| where orders.user_id = users.id
| |
| )
| |
| </syntaxhighlight>
| |
| | |
| ===서브쿼리 Where 절=== | | ===서브쿼리 Where 절=== |
| 때로는 주어진 값과 서브쿼리의 결과를 비교하는 "where" 절을 구성해야 할 때가 있습니다. 이를 위해 클로저와 값을 <code>where</code> 메소드에 전달할 수 있습니다. 예를 들어, 다음 쿼리는 주어진 유형의 최근 "membership(회원권)"을 가진 모든 사용자를 조회합니다;
| | ===풀텍스트 Where 절=== |
| | |
| <syntaxhighlight lang='php'>
| |
| use App\Models\User;
| |
| use Illuminate\Database\Query\Builder;
| |
|
| |
| $users = User::where(function (Builder $query) {
| |
| $query->select('type')
| |
| ->from('membership')
| |
| ->whereColumn('membership.user_id', 'users.id')
| |
| ->orderByDesc('membership.start_date')
| |
| ->limit(1);
| |
| }, 'Pro')->get();
| |
| </syntaxhighlight>
| |
| | |
| 또는, 컬럼을 서브쿼리 결과와 비교하는 "where" 절을 구성해야 할 수도 있습니다. 이를 위해 컬럼, 연산자, 클로저를 <code>where</code> 메소드에 전달할 수 있습니다. 예를 들어, 다음 쿼리는 금액이 평균보다 적은 모든 소득 기록을 검색합니다;
| |
| | |
| <syntaxhighlight lang='php'>
| |
| use App\Models\Income;
| |
| use Illuminate\Database\Query\Builder;
| |
|
| |
| $incomes = Income::where('amount', '<', function (Builder $query) {
| |
| $query->selectRaw('avg(i.amount)')->from('incomes as i');
| |
| })->get();
| |
| </syntaxhighlight>
| |
| | |
| ===전체 텍스트 Where 절===
| |
| {{WARNING}}
| |
| 전체 텍스트 Where 절은 현재 MySQL과 PostgreSQL에서 지원됩니다.
| |
| {{/WARNING}}
| |
| | |
| <code>whereFullText</code>와 <code>orWhereFullText</code> 메소드는 전체 텍스트 인덱스가 있는 컬럼에 대해 쿼리에 전체 텍스트 "where" 절을 추가하는 데 사용될 수 있습니다. 이러한 메소드는 Laravel에 의해 기본 데이터베이스 시스템에 맞는 적절한 SQL로 변환됩니다. 예를 들어, MySQL을 사용하는 애플리케이션에서는 <code>MATCH AGAINST</code> 절이 생성됩니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| $users = DB::table('users')
| |
| ->whereFullText('bio', 'web developer')
| |
| ->get();
| |
| </syntaxhighlight>
| |
| | |
| ==정렬, 그룹화, 리미트, 오프셋== | | ==정렬, 그룹화, 리미트, 오프셋== |
| ===정렬=== | | ===정렬=== |
887번째 줄: |
148번째 줄: |
| ==비관적 락== | | ==비관적 락== |
| ==디버깅== | | ==디버깅== |
| | ==참고== |
| | * https://laravel.com/docs/11.x/queries |
| | |
| | [[분류: Laravel]] |