メインコンテンツにスキップ

生のクエリ

警告

Prisma ORM 5.19.0 で、TypedSQL がリリースされました。TypedSQL は、型安全でワークフローへの追加がさらに容易な SQL クエリを記述する新しい方法です。

可能な限り、以下のレガシーな生のクエリではなく、TypedSQL クエリを使用することを強くお勧めします。

Prisma Client は、データベースに生のクエリを送信するオプションをサポートしています。以下の場合に、生のクエリを使用することをお勧めします。

生のクエリは、Prisma ORM がサポートするすべてのリレーショナルデータベースで利用できます。さらに、バージョン 3.9.0 以降では MongoDB でも生のクエリがサポートされています。詳細については、関連セクションを参照してください。

リレーショナルデータベースでの生のクエリ

リレーショナルデータベースの場合、Prisma Client は生のクエリを送信できる4つのメソッドを公開しています。これらを使用できます。

  • $queryRaw: 実際のレコードを返す(例: SELECT を使用)。
  • $executeRaw: 影響を受けた行数を返す(例: UPDATE または DELETE の後)。
  • $queryRawUnsafe: 生の文字列を使用して実際のレコードを返す(例: SELECT を使用)。
  • $executeRawUnsafe: 生の文字列を使用して影響を受けた行数を返す(例: UPDATE または DELETE の後)。

名前に「Unsafe」が含まれるメソッドははるかに柔軟ですが、**SQL インジェクションに対してコードが脆弱になる重大なリスク**があります。

他の2つのメソッドは、単純なテンプレートタグで使用しても安全であり、文字列の構築や連結は行いません。**ただし**、これらのメソッドが特定の方法で使用される場合、SQL インジェクションを引き起こす可能性があるため、より複雑なユースケースでは注意が必要です。詳細については、以下のSQL インジェクション対策セクションを参照してください。

注意: 上記リストのすべてのメソッドは、一度に**1つ**のクエリしか実行できません。2つ目のクエリを追加することはできません。例えば、select 1; select 2; でいずれかのメソッドを呼び出しても機能しません。

$queryRaw

$queryRaw は実際のデータベースレコードを返します。例えば、次の SELECT クエリは、User テーブルの各レコードのすべてのフィールドを返します。

const result = await prisma.$queryRaw`SELECT * FROM User`;

このメソッドはタグ付きテンプレートとして実装されており、変数を簡単に挿入できるテンプレートリテラルを渡すことができます。これにより、Prisma Client は SQL インジェクションから安全なプリペアドステートメントを作成します。

const email = "emelie@prisma.io";
const result = await prisma.$queryRaw`SELECT * FROM User WHERE email = ${email}`;

Prisma.sql ヘルパーを使用することもできます。実際、$queryRaw メソッドはテンプレート文字列または Prisma.sql ヘルパー**のみ**を受け入れます。

const email = "emelie@prisma.io";
const result = await prisma.$queryRaw(Prisma.sql`SELECT * FROM User WHERE email = ${email}`);
警告

信頼できない入力をこのメソッドに渡されるクエリに組み込むために文字列ビルディングを使用すると、SQL インジェクション攻撃の可能性が開かれます。SQL インジェクション攻撃は、データの変更または削除を引き起こす可能性があります。推奨されるメカニズムは、このメソッドを実行する時点でクエリのテキストを含めることです。このリスクに関する詳細およびそれを防ぐ方法の例については、以下のSQL インジェクション対策セクションを参照してください。

考慮事項

以下に注意してください。

  • テンプレート変数は SQL 文字列リテラル内では使用できません。例えば、以下のクエリは**機能しません**。

    const name = "Bob";
    await prisma.$queryRaw`SELECT 'My name is ${name}';`;

    代わりに、文字列全体を変数として渡すか、文字列連結を使用することができます。

    const name = "My name is Bob";
    await prisma.$queryRaw`SELECT ${name};`;
    const name = "Bob";
    await prisma.$queryRaw`SELECT 'My name is ' || ${name};`;
  • テンプレート変数は、データ値(上記の例の email など)にのみ使用できます。列名、テーブル名、データベース名などの識別子や、SQL キーワードには変数は使用できません。例えば、以下の2つのクエリは**機能しません**。

    const myTable = "user";
    await prisma.$queryRaw`SELECT * FROM ${myTable};`;
    const ordering = "desc";
    await prisma.$queryRaw`SELECT * FROM Table ORDER BY ${ordering};`;
  • Prisma は、$queryRaw および $queryRawUnsafe によって返されるすべてのデータベース値を対応する JavaScript の型にマッピングします。詳細はこちら

  • $queryRaw は PostgreSQL データベースでの動的なテーブル名をサポートしていません。詳細はこちら

戻り値の型

$queryRaw は配列を返します。各オブジェクトはデータベースレコードに対応します。

[
{ id: 1, email: "emelie@prisma.io", name: "Emelie" },
{ id: 2, email: "yin@prisma.io", name: "Yin" },
]

$queryRaw の結果に型を付けることもできます。

署名

$queryRaw<T = unknown>(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): PrismaPromise<T>;

$queryRaw 結果の型付け

PrismaPromise<T> は、ジェネリック型パラメータ T を使用します。$queryRaw メソッドを呼び出すときに T の型を決定できます。次の例では、$queryRawUser[] を返します。

// import the generated `User` type from the `@prisma/client` module
import { User } from "@prisma/client";

const result = await prisma.$queryRaw<User[]>`SELECT * FROM User`;
// result is of type: `User[]`

注意: 型を指定しない場合、$queryRaw はデフォルトで unknown になります。

モデルの**特定のフィールド**を選択する場合、または関連を含める場合は、結果が適切に型付けされるようにするために、Prisma Client の生成された型を活用することに関するドキュメントを参照してください。

生の SQL を使用する際の型の注意点

$queryRaw の結果に型を付ける場合、生データが常に推奨される TypeScript の型と一致するとは限りません。例えば、次の Prisma モデルには published という名前の Boolean フィールドが含まれています。

model Post {
id Int @id @default(autoincrement())
published Boolean @default(false)
title String
content String?
}

次のクエリはすべての投稿を返します。次に、各 Postpublished フィールドの値を表示します。

const result = await prisma.$queryRaw<Post[]>`SELECT * FROM Post`;

result.forEach((x) => {
console.log(x.published);
});

通常の CRUD クエリの場合、Prisma Client のクエリエンジンはすべてのデータベースで戻り値の型を標準化します。**生のクエリでは標準化されません**。データベースプロバイダが MySQL の場合、返される値は 1 または 0 です。しかし、データベースプロバイダが PostgreSQL の場合、値は true または false になります。

注意: Prisma は JavaScript の整数を INT8 として PostgreSQL に送信します。これは、INT4 のみを入力として受け入れるユーザー定義関数と競合する可能性があります。PostgreSQL データベースと組み合わせて $queryRaw を使用する場合は、入力型を INT8 に更新するか、クエリパラメータを INT4 にキャストしてください。

PostgreSQL の動的テーブル名

テーブル名を補間することはできません。これは、$queryRaw で動的なテーブル名を使用できないことを意味します。代わりに、次のように$queryRawUnsafeを使用する必要があります。

let userTable = "User";
let result = await prisma.$queryRawUnsafe(`SELECT * FROM ${userTable}`);

$queryRawUnsafe をユーザー入力と組み合わせて使用すると、SQL インジェクション攻撃のリスクがあることに注意してください。詳細はこちら

$queryRawUnsafe()

$queryRawUnsafe() メソッドを使用すると、生文字列(またはテンプレート文字列)をデータベースに渡すことができます。

警告

このメソッドをユーザー入力(つまり、SELECT * FROM table WHERE columnx = ${userInput})と共に使用すると、SQL インジェクション攻撃の可能性が開かれます。SQL インジェクション攻撃は、データの変更または削除を引き起こす可能性があります。

可能な限り、代わりに $queryRaw メソッドを使用する必要があります。正しく使用した場合、$queryRaw メソッドははるかに安全ですが、特定の状況下では $queryRaw メソッドも脆弱になる可能性があることに注意してください。詳細については、以下のSQL インジェクション対策セクションを参照してください。

次のクエリは、User テーブルの各レコードのすべてのフィールドを返します。

// import the generated `User` type from the `@prisma/client` module
import { User } from "@prisma/client";

const result = await prisma.$queryRawUnsafe("SELECT * FROM User");

パラメーター化されたクエリを実行することもできます。次の例では、メールアドレスに文字列 emelie@prisma.io が含まれるすべてのユーザーを返します。

prisma.$queryRawUnsafe("SELECT * FROM users WHERE email = $1", "emelie@prisma.io");

注意: Prisma は JavaScript の整数を INT8 として PostgreSQL に送信します。これは、INT4 のみを入力として受け入れるユーザー定義関数と競合する可能性があります。PostgreSQL データベースと組み合わせてパラメータ化された $queryRawUnsafe クエリを使用する場合は、入力型を INT8 に更新するか、クエリパラメータを INT4 にキャストしてください。

パラメーター化されたクエリの使用に関する詳細については、以下のパラメーター化されたクエリセクションを参照してください。

署名

$queryRawUnsafe<T = unknown>(query: string, ...values: any[]): PrismaPromise<T>;

$executeRaw

$executeRaw は、UPDATEDELETE のようなデータベース操作によって影響を受けた行数を返します。この関数はデータベースレコードを**返しません**。次のクエリはデータベース内のレコードを更新し、更新されたレコードの数を返します。

const result: number =
await prisma.$executeRaw`UPDATE User SET active = true WHERE emailValidated = true`;

このメソッドはタグ付きテンプレートとして実装されており、変数を簡単に挿入できるテンプレートリテラルを渡すことができます。これにより、Prisma Client は SQL インジェクションから安全なプリペアドステートメントを作成します。

const emailValidated = true;
const active = true;

const result: number =
await prisma.$executeRaw`UPDATE User SET active = ${active} WHERE emailValidated = ${emailValidated};`;
警告

信頼できない入力をこのメソッドに渡されるクエリに組み込むために文字列ビルディングを使用すると、SQL インジェクション攻撃の可能性が開かれます。SQL インジェクション攻撃は、データの変更または削除を引き起こす可能性があります。推奨されるメカニズムは、このメソッドを実行する時点でクエリのテキストを含めることです。このリスクに関する詳細およびそれを防ぐ方法の例については、以下のSQL インジェクション対策セクションを参照してください。

考慮事項

以下に注意してください。

  • $executeRaw は、単一の文字列内に複数のクエリをサポートしていません(例: ALTER TABLECREATE TABLE を同時に)。

  • Prisma Client はプリペアドステートメントを送信し、プリペアドステートメントは SQL ステートメントのサブセットのみを許可します。例えば、START TRANSACTION は許可されません。MySQL がプリペアドステートメントで許可する構文の詳細はこちらで確認できます

  • PREPAREALTER をサポートしていません - 回避策を参照してください。

  • テンプレート変数は SQL 文字列リテラル内では使用できません。例えば、以下のクエリは**機能しません**。

    const name = "Bob";
    await prisma.$executeRaw`UPDATE user SET greeting = 'My name is ${name}';`;

    代わりに、文字列全体を変数として渡すか、文字列連結を使用することができます。

    const name = "My name is Bob";
    await prisma.$executeRaw`UPDATE user SET greeting = ${name};`;
    const name = "Bob";
    await prisma.$executeRaw`UPDATE user SET greeting = 'My name is ' || ${name};`;
  • テンプレート変数は、データ値(上記の例の email など)にのみ使用できます。列名、テーブル名、データベース名などの識別子や、SQL キーワードには変数は使用できません。例えば、以下の2つのクエリは**機能しません**。

    const myTable = "user";
    await prisma.$executeRaw`UPDATE ${myTable} SET active = true;`;
    const ordering = "desc";
    await prisma.$executeRaw`UPDATE User SET active = true ORDER BY ${desc};`;

戻り値の型

$executeRawnumber を返します。

署名

$executeRaw<T = unknown>(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): PrismaPromise<number>;

$executeRawUnsafe()

$executeRawUnsafe() メソッドを使用すると、生文字列(またはテンプレート文字列)をデータベースに渡すことができます。$executeRaw と同様に、データベースレコードは**返さず**、影響を受けた行数を返します。

警告

このメソッドをユーザー入力(つまり、SELECT * FROM table WHERE columnx = ${userInput})と共に使用すると、SQL インジェクション攻撃の可能性が開かれます。SQL インジェクション攻撃は、データの変更または削除を引き起こす可能性があります。

可能な限り、代わりに $executeRaw メソッドを使用する必要があります。正しく使用した場合、$executeRaw メソッドははるかに安全ですが、特定の状況下では $executeRaw メソッドも脆弱になる可能性があることに注意してください。詳細については、以下のSQL インジェクション対策セクションを参照してください。

次の例では、テンプレート文字列を使用してデータベース内のレコードを更新します。その後、更新されたレコードの数を返します。

const emailValidated = true;
const active = true;

const result = await prisma.$executeRawUnsafe(
`UPDATE User SET active = ${active} WHERE emailValidated = ${emailValidated}`
);

同じことをパラメーター化されたクエリとして記述できます。

const result = prisma.$executeRawUnsafe(
"UPDATE User SET active = $1 WHERE emailValidated = $2",
"yin@prisma.io",
true
);

パラメーター化されたクエリの使用に関する詳細については、以下のパラメーター化されたクエリセクションを参照してください。

署名

$executeRawUnsafe<T = unknown>(query: string, ...values: any[]): PrismaPromise<number>;

生クエリの型マッピング

Prisma は、$queryRaw および $queryRawUnsafe によって返されるすべてのデータベース値を、対応するJavaScript の型にマッピングします。この動作は、findMany() のような通常の Prisma クエリメソッドと同じです。

情報

機能の利用可能性

  • v3.14.x と v3.15.x では、生のクエリの型マッピングはプレビュー機能 improvedQueryRaw で利用可能でした。バージョン 4.0.0 で生のクエリの型マッピングを一般利用可能(GA)にしたため、バージョン 4.0.0 以降では improvedQueryRaw を使用する必要はありません。
  • バージョン 4.0.0 より前は、SQLite で生のクエリの型マッピングは利用できませんでした。

例として、テーブルから BigIntBytesDecimalDate 型の列を選択する生のクエリを取り上げます。

const result = await prisma.$queryRaw`SELECT bigint, bytes, decimal, date FROM "Table";`;

console.log(result);
表示CLI結果
{ bigint: BigInt("123"), bytes: <Buffer 01 02>), decimal: Decimal("12.34"), date: Date("<some_date>") }

result オブジェクトでは、データベース値が対応する JavaScript の型にマッピングされています。

以下の表は、データベースで使用される型と、生クエリによって返される JavaScript の型との変換を示しています。

データベース型JavaScript 型
テキスト文字列
32ビット整数数値
32ビット符号なし整数BigInt
浮動小数点数数値
倍精度数値数値
64ビット整数BigInt
Decimal / 数値Decimal
バイトUint8Arrayv6より前: Buffer
Jsonオブジェクト
DateTime日付
日付日付
時刻日付
Uuid文字列
Xml文字列

各データベースの型の正確な名前はデータベースによって異なります。例えば、ブール型は PostgreSQL では boolean、CockroachDB では STRING と呼ばれます。スカラー型リファレンスで、各データベースの型の完全な詳細を確認してください。

生クエリの型キャスト動作

Prisma Client の生クエリでは、パラメータが SQL 関数またはクエリの期待される型である必要があります。Prisma Client は、微妙な暗黙的なキャストを行いません。

例として、PostgreSQL の LENGTH 関数を使用する次のクエリを考えてみましょう。この関数は入力として text 型のみを受け入れます。

await prisma.$queryRaw`SELECT LENGTH(${42});`;

このクエリはエラーを返します。

// ERROR: function length(integer) does not exist
// HINT: No function matches the given name and argument types. You might need to add explicit type casts.

この場合の解決策は、42 を明示的に text 型にキャストすることです。

await prisma.$queryRaw`SELECT LENGTH(${42}::text);`;
情報

機能の利用可能性: この機能はバージョン 4.0.0 以降で一般利用可能(GA)です。v3.14.x および v3.15.x では、プレビュー機能 improvedQueryRaw で利用可能でした。

バージョン 4.0.0 より前の上記の例では、Prisma ORM は 42 を暗黙的に text に強制変換し、明示的なキャストを必要としませんでした。

一方、以下の生クエリは現在正しく動作し、整数結果を返し、以前は失敗していました。

await prisma.$queryRaw`SELECT ${1.5}::int as int`;

// Now: [{ int: 2 }]
// Before: db error: ERROR: incorrect binary data format in bind parameter 1

トランザクション

2.10.0 以降では、トランザクション内で .$executeRaw() および .$queryRaw() を使用できます。

変数の使用

$executeRaw$queryRawタグ付きテンプレートとして実装されています。タグ付きテンプレートは、Prisma Client で生 SQL と変数を使用する推奨される方法です。

次の例には、${userId} という名前のプレースホルダーが含まれています。

const userId = 42;
const result = await prisma.$queryRaw`SELECT * FROM User WHERE id = ${userId};`;

$queryRaw および $executeRaw のタグ付きテンプレートバージョンを使用する利点には以下が含まれます。

  • Prisma Client はすべての変数をエスケープします。
  • タグ付きテンプレートはデータベースに依存しません。変数を $1 (PostgreSQL) または ? (MySQL) のどちらで記述するかを覚える必要はありません。
  • SQL Template Tag便利なヘルパーへのアクセスを提供します。
  • 埋め込みの、名前付き変数は読みやすいです。

注意: タグ付きテンプレートのプレースホルダーにテーブル名や列名を渡すことはできません。例えば、SELECT ? として、条件に基づいて *id, name を渡すことはできません。

タグ付きテンプレートヘルパー

Prisma Client は特にSQL Template Tagを使用しており、多くのヘルパーを公開しています。例えば、次のクエリは join() を使用して ID のリストを渡します。

import { Prisma } from "@prisma/client";

const ids = [1, 3, 5, 10, 20];
const result = await prisma.$queryRaw`SELECT * FROM User WHERE id IN (${Prisma.join(ids)})`;

次の例では、emptysql ヘルパーを使用して、userName が空かどうかによってクエリを変更します。

import { Prisma } from "@prisma/client";

const userName = "";
const result = await prisma.$queryRaw`SELECT * FROM User ${
userName ? Prisma.sql`WHERE name = ${userName}` : Prisma.empty // Cannot use "" or NULL here!
}`;

ALTER 制限 (PostgreSQL)

PostgreSQL は、プリペアドステートメントでの ALTER の使用をサポートしていません。つまり、次のクエリは**機能しません**。

await prisma.$executeRaw`ALTER USER prisma WITH PASSWORD "${password}"`;
await prisma.$executeRaw(Prisma.sql`ALTER USER prisma WITH PASSWORD "${password}"`);

次のクエリを使用することはできますが、${password} がエスケープされないため、これは潜在的に**安全ではありません**ので注意してください。

await prisma.$executeRawUnsafe('ALTER USER prisma WITH PASSWORD "$1"', password})

非サポート型

Unsupportedは、$queryRaw または $queryRawUnsafe で使用する前に、Prisma Client がサポートする型にキャストする必要があります。例えば、location フィールドに Unsupported 型を持つ次のモデルを考えてみましょう。

model Country {
location Unsupported("point")?
}

このサポートされていないフィールドに対する次のクエリは**機能しません**。

await prisma.$queryRaw`SELECT location FROM Country;`;

代わりに、**もしあなたの Unsupported カラムがキャストをサポートしているなら**、Unsupported フィールドをサポートされている任意の Prisma Client の型にキャストしてください。

最も一般的に Unsupported 列をキャストしたい型は String です。例えば、PostgreSQL では、これは text 型にマッピングされます。

await prisma.$queryRaw`SELECT location::text FROM Country;`;

したがって、データベースは Prisma Client がサポートするデータの String 表現を提供します。

サポートされている Prisma 型の詳細については、関連するデータベースのPrisma コネクタの概要を参照してください。

SQL インジェクション対策

Prisma Client で SQL インジェクションを回避する理想的な方法は、可能な限り ORM モデルを使用してクエリを実行することです。

それが不可能な場合で、生のクエリが必要な場合は、Prisma Client が様々な生メソッドを提供しますが、これらのメソッドを安全に使用することが重要です。

このセクションでは、これらのメソッドを安全かつ安全でない方法で使用する様々な例を提供します。これらの例はPrisma Playgroundでテストできます。

$queryRaw および $executeRaw

$queryRaw および $executeRaw のシンプルで安全な使い方

これらのメソッドは、タグ付きテンプレートを使用する際にすべての変数をエスケープし、すべてのクエリをプリペアドステートメントとして送信することで、SQL インジェクションのリスクを軽減できます。

$queryRaw`...`; // Tagged template
$executeRaw`...`; // Tagged template

次の例は SQL インジェクションに対して安全です ✅

const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`;
const result = await prisma.$queryRaw`SELECT id, name FROM "User" WHERE name = ${inputString}`;

console.log(result);

$queryRaw および $executeRaw の安全でない使い方

ただし、これらのメソッドを安全でない方法で使用することも可能です。

一つの方法は、ユーザー入力を安全でない方法で連結するタグ付きテンプレートを人工的に生成することです。

次の例は SQL インジェクションに対して脆弱です ❌

// Unsafely generate query text
const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`; // SQL Injection
const query = `SELECT id, name FROM "User" WHERE name = ${inputString}`;

// Version for Typescript
const stringsArray: any = [...[query]];

// Version for Javascript
const stringsArray = [...[query]];

// Use the `raw` property to impersonate a tagged template
stringsArray.raw = [query];

// Use queryRaw
const result = await prisma.$queryRaw(stringsArray);
console.log(result);

これらのメソッドを脆弱にするもう一つの方法は、Prisma.raw 関数の誤用です。

以下の例はすべて SQL インジェクションに対して脆弱です ❌

const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`;
const result = await prisma.$queryRaw`SELECT id, name FROM "User" WHERE name = ${Prisma.raw(
inputString
)}`;
console.log(result);
const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`;
const result = await prisma.$queryRaw(
Prisma.raw(`SELECT id, name FROM "User" WHERE name = ${inputString}`)
);
console.log(result);
const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`;
const query = Prisma.raw(`SELECT id, name FROM "User" WHERE name = ${inputString}`);
const result = await prisma.$queryRaw(query);
console.log(result);

より複雑なシナリオで $queryRaw および $executeRaw を安全に使用する

クエリの実行とは別に生クエリを構築する

生のクエリを別の場所で、またはパラメータとは別に構築したい場合は、以下のいずれかの方法を使用する必要があります。

この例では、sql ヘルパーメソッドが変数を含めてクエリテキストを安全に構築するために使用されています。これは SQL インジェクションに対して安全です ✅

// inputString can be untrusted input
const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`;

// Safe if the text query below is completely trusted content
const query = Prisma.sql`SELECT id, name FROM "User" WHERE name = ${inputString}`;

const result = await prisma.$queryRaw(query);
console.log(result);

この例は SQL インジェクションに対して安全 ✅ です。sql ヘルパーメソッドは、入力値のパラメータマーカーを含むクエリテキストを構築するために使用されています。各変数はマーカーシンボル(MySQL の場合は ?、PostgreSQL の場合は $1$2 など)で表されます。この例は PostgreSQL クエリのみを示しています。

// Version for Typescript
const query: any;

// Version for Javascript
const query;

// Safe if the text query below is completely trusted content
query = Prisma.sql`SELECT id, name FROM "User" WHERE name = $1`;

// inputString can be untrusted input
const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`;
query.values = [inputString];

const result = await prisma.$queryRaw(query);
console.log(result);

注記: PostgreSQL 変数は $1 などで表されます。

生クエリを別の場所または段階的に構築する

クエリを実行する場所以外の場所で生のクエリを構築したい場合、理想的な方法は、クエリのセグメントから Sql オブジェクトを作成し、それにパラメータ値を渡すことです。

次の例では、パラメーター化する変数が2つあります。Prisma.sql に渡されるクエリ文字列が信頼できるコンテンツのみを含んでいる限り、この例は SQL インジェクションに対して安全です ✅

// Example is safe if the text query below is completely trusted content
const query1 = `SELECT id, name FROM "User" WHERE name = `; // The first parameter would be inserted after this string
const query2 = ` OR name = `; // The second parameter would be inserted after this string

const inputString1 = "Fred";
const inputString2 = `'Sarah' UNION SELECT id, title FROM "Post"`;

const query = Prisma.sql([query1, query2, ""], inputString1, inputString2);
const result = await prisma.$queryRaw(query);
console.log(result);

注: Prisma.sql の最初のパラメータとして渡される文字列配列は、sql 関数がパラメータの数よりも1つ多いクエリセグメントを期待するため、最後に空の文字列を持つ必要があることに注意してください。

生クエリを1つの大きな文字列に構築したい場合でも可能です。ただし、これは潜在的に危険な Prisma.raw メソッドを使用するため、注意が必要です。また、Prisma が通常提供するような関連データベースのマーカーを提供できないため、データベースに正しいパラメーターマーカーを使用してクエリを構築する必要があります。

Prisma.raw に渡されるクエリ文字列が信頼できるコンテンツのみを含んでいる限り、次の例は SQL インジェクションに対して安全です ✅

// Version for Typescript
const query: any;

// Version for Javascript
const query;

// Example is safe if the text query below is completely trusted content
const query1 = `SELECT id, name FROM "User" `;
const query2 = `WHERE name = $1 `;

query = Prisma.raw(`${query1}${query2}`);

// inputString can be untrusted input
const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`;
query.values = [inputString];

const result = await prisma.$queryRaw(query);
console.log(result);

$queryRawUnsafe および $executeRawUnsafe

$queryRawUnsafe および $executeRawUnsafe を安全でない方法で使用する

タグ付きテンプレートを使用できない場合は、代わりに$queryRawUnsafeまたは$executeRawUnsafeを使用できます。ただし、**これらの関数はコード内の SQL インジェクション脆弱性のリスクを大幅に高めることに注意してください**。

次の例では queryinputString を連結しています。この例では Prisma Client は inputString をエスケープ**できません**❌。これにより、SQL インジェクションに対して脆弱になります。

const inputString = '"Sarah" UNION SELECT id, title, content FROM Post'; // SQL Injection
const query = "SELECT id, name, email FROM User WHERE name = " + inputString;
const result = await prisma.$queryRawUnsafe(query);

console.log(result);

パラメーター化されたクエリ

タグ付きテンプレートの代替として、$queryRawUnsafe は、各変数がシンボル(MySQL の場合は ?、PostgreSQL の場合は $1$2 など)で表される標準的なパラメーター化クエリをサポートしています。この例は PostgreSQL クエリのみを示しています。

次の例は SQL インジェクションに対して安全です ✅

const userName = "Sarah";
const email = "sarah@prisma.io";
const result = await prisma.$queryRawUnsafe(
"SELECT * FROM User WHERE (name = $1 OR email = $2)",
userName,
email
);

: PostgreSQL 変数は $1 および $2 で表されます。

タグ付きテンプレートと同様に、このように変数を提供した場合、Prisma Client はすべての変数をエスケープします。

注意: パラメータ化されたクエリにテーブル名や列名を変数として渡すことはできません。例えば、SELECT ? として、条件に基づいて *id, name を渡すことはできません。

パラメーター化された PostgreSQL ILIKE クエリ

ILIKE を使用する場合、% ワイルドカード文字はクエリ (string) ではなく、変数自体に含める必要があります。この例は SQL インジェクションに対して安全です ✅。

const userName = "Sarah";
const emailFragment = "prisma.io";
const result = await prisma.$queryRawUnsafe(
'SELECT * FROM "User" WHERE (name = $1 OR email ILIKE $2)',
userName,
`%${emailFragment}`
);

: %$2 を引数として使用しても機能しません。

MongoDB での生のクエリ

MongoDB のバージョン 3.9.0 以降では、Prisma Client は生のクエリを送信できる3つのメソッドを公開しています。これらを使用できます。

  • $runCommandRaw: データベースに対してコマンドを実行します。
  • <model>.findRaw: フィルターに一致するドキュメントをゼロ個以上見つけます。
  • <model>.aggregateRaw: コレクションに対して集約操作を実行します。

$runCommandRaw()

$runCommandRaw() は、データベースに対して生の MongoDB コマンドを実行します。入力として、以下の例外を除き、すべてのMongoDB データベースコマンドを受け入れます。

$runCommandRaw() を使用して MongoDB データベースコマンドを実行する場合、以下の点に注意してください。

  • $runCommandRaw() を呼び出すときに渡すオブジェクトは、MongoDB データベースコマンドの構文に従う必要があります。
  • MongoDB データベースコマンドに適切なロールでデータベースに接続する必要があります。

次の例では、2つのレコードが同じ _id で挿入されます。これは通常のドキュメント検証をバイパスします。

prisma.$runCommandRaw({
insert: "Pets",
bypassDocumentValidation: true,
documents: [
{
_id: 1,
name: "Felinecitas",
type: "Cat",
breed: "Russian Blue",
age: 12,
},
{
_id: 1,
name: "Nao Nao",
type: "Dog",
breed: "Chow Chow",
age: 2,
},
],
});
警告

"find" または "aggregate" コマンドを含むクエリには $runCommandRaw() を使用しないでください。すべてのデータを取得できない可能性があります。これは、MongoDB が MongoDB セッションにアタッチされたカーソルを返すためであり、毎回同じ MongoDB セッションにヒットするとは限らないためです。これらのクエリには、代わりに特殊なfindRaw()およびaggregateRaw()メソッドを使用する必要があります。

戻り値の型

$runCommandRaw() は、入力によって形状が異なる JSON オブジェクトを返します。

署名

$runCommandRaw(command: InputJsonObject): PrismaPromise<JsonObject>;

findRaw()

<model>.findRaw() は実際のデータベースレコードを返します。User コレクションでフィルターに一致するドキュメントをゼロ個以上見つけます。

const result = await prisma.user.findRaw({
filter: { age: { $gt: 25 } },
options: { projection: { _id: false } },
});

戻り値の型

<model>.findRaw() は、入力によって形状が異なる JSON オブジェクトを返します。

署名

<model>.findRaw(args?: {filter?: InputJsonObject, options?: InputJsonObject}): PrismaPromise<JsonObject>;
  • filter: クエリの述語フィルター。指定されていない場合、コレクション内のすべてのドキュメントが述語に一致します。
  • options: find コマンドに渡す追加オプション。

aggregateRaw()

<model>.aggregateRaw() は集約されたデータベースレコードを返します。User コレクションに対して集約操作を実行します。

const result = await prisma.user.aggregateRaw({
pipeline: [
{ $match: { status: "registered" } },
{ $group: { _id: "$country", total: { $sum: 1 } } },
],
});

戻り値の型

<model>.aggregateRaw() は、入力によって形状が異なる JSON オブジェクトを返します。

署名

<model>.aggregateRaw(args?: {pipeline?: InputJsonObject[], options?: InputJsonObject}): PrismaPromise<JsonObject>;

注意点

ObjectIdDate のようなカスタムオブジェクトを扱う場合、それらをMongoDB 拡張 JSON 仕様に従って渡す必要があります。例:

const result = await prisma.user.aggregateRaw({
pipeline: [
{ $match: { _id: { $oid: id } } }
// ^ notice the $oid convention here
],
});

© . All rights reserved.