検索
ホームページバックエンド開発Python チュートリアル生の SQL を安全に作成するためのライブラリ

PropelAuth での私の責任の 1 つは、さまざまな言語/フレームワークでサンプル アプリ/ガイドを作成することです。それは本当に私の仕事の中で最も楽しい部分の一つです。新しいものから古いものまで、さまざまなスタックを試してみて、お客様をサポ​​ートする最善の方法を見つけ出すことができます。

そのため、多くのプロジェクトをゼロから作成することになります。新しいプロジェクトを開始するときは常に、いくつかの重要な選択をしなければなりません。そして、私が多くの時間を費やす傾向がある決定の 1 つは次のとおりです。

どの DB ライブラリを使用すればよいですか?

私にとって、私が惹かれるライブラリは、私が書いているコードと SQL クエリ自体の間に抽象化の層が少ないものです

その理由の 1 つは、単なる実用性です。私は頻繁に言語を切り替えるため、特定の ORM を流暢に理解する時間があまりありません。私も過去に大量のデータ サイエンス コンポーネントを含む仕事に就いていたため、SQL は非常に使いやすいものです。

しかし、私は「魔法」を嫌う傾向にある開発者でもあります。そのため、生成された SQL がどのようなものになるのか簡単に判断できないライブラリや、自分の時間を費やしていると感じるライブラリは避けています。 「X に参加する方法」をグーグルで検索し、続いて「2 つの条件で X に参加する方法」を検索します。

この投稿では、私が頻繁に利用するいくつかのライブラリと、試してみたいと思っているライブラリに焦点を当てたいと思いました。これらはすべて、私が作成したコードと SQL との違いを最小限に抑えるよう努めています。実行されました。

私の個人的なお気に入り: SQLx

私のお気に入りの Rust クレートの 1 つは SQLx です。

彼ら自身の言葉で:

SQLx は コンパイル時にチェックされるクエリ をサポートします。ただし、クエリを構築するための Rust API や DSL (ドメイン固有言語) を提供することでこれを行うわけではありません。代わりに、通常の SQL を入力として受け取り、それがデータベースに対して有効であることを確認するマクロが提供されます。これがどのように機能するかというと、コンパイル時に SQLx が開発 DB に接続して、データベース自体に SQL クエリを検証 (そして情報を返す) させるというものです。

言い換えると、SQLx では次のようなクエリを作成できます。

let row = sqlx::query!(r#"
    SELECT enail
    FROM user
    WHERE user_id = ?
"#, user_id)
  .fetch_one(&pool)
  .await?;

これは標準的なように思えるかもしれませんが、コードをコンパイルすると次のようなエラーが発生します:

error returned from database: column "enail" of relation "user" does not exist

これと同じコンパイル時のチェックは、複雑なクエリにも適用されます。

SELECT job_id, job_data 
FROM job_queue
WHERE job_status = 'Queued' AND run_at >= NOW()
ORDER BY run_at ASC
FOR UPDATE SKIP LOCKE -- oops
LIMIT 1
error returned from database: syntax error at or near "LOCKE"

クエリはデータベースに対してチェックされるため、インストールされている拡張機能でも機能します。

なぜこれがクールなのでしょうか?

これの驚くべき点は、文字通り SQL を書いているだけだということです。しかし、生の SQL を書くこともできる postgres のようなクレートとは異なり、SQLx は愚かな間違いを防ぐことができます。

これには多少のコストがかかります。コンパイル時にデータベースに依存することになりますが、SQLx は「オフライン モード」でこれに対処します。 DB が使用可能な場合は、検証されたすべてのクエリを含むファイルを生成できます。その後、ビルドで SQLx がデータベースの代わりにこのファイルをチェックします。

私が書いたコードと実行される SQL の間の違いを最小限に抑えるという私の探求において、SQLx を使用すると違いがなく、それを得るために安全性を犠牲にする必要もありませんでした。

PgTyped を使用して SQL の TS インターフェイスを生成します

JavaScript/TypeScript エコシステムではよくあることですが、ここにはたくさんのオプションがあります。

データベースから TS タイプを生成し、クエリ ビルダーと生の SQL を記述する方法の両方を提供する Kysely のようなオプションがあります。 Drizzle というクエリ ビルダーがありますが、その目標は、作成した TS コードと生成された SQL の間の差を減らすことであると述べられています。まだ試していない SQLx ポートもあります。

しかし、ここで私が探しているものに最もよく一致するライブラリは PgTyped です。 PgTyped を使用すると、次のように別のファイルでクエリを定義します。

/* @name FindEmailById */
SELECT email FROM user WHERE user_id = :userId;

その後、コマンド npx pgtyped -c config.json を実行すると、スキーマに基づいて適切な型の関数が生成されます。

export interface IFindEmailByIdParams {
    userId?: string | null;
}
export interface IFindEmailByIdResult {
    email: string
}export const findEmailById = new PreparedQuery



<p>その関数を呼び出して DB から結果を取得できます。重要なのは、クエリが間違っている場合 (存在しない列を参照しているとしましょう)、次のようなエラーが表示されることです:<br>
</p>

<pre class="brush:php;toolbar:false">Error in query. Details: {
  errorCode: 'errorMissingColumn',
  hint: 'Perhaps you meant to reference the column "user.email".',
  message: 'column "enail" does not exist',
  position: '7'
}

これは、生の SQL を安全に記述できるだけでなく、アプリケーション コードで呼び出す (またはテストでモックする) ための優れた TS 抽象化を取得できることを意味します。

PgTyped の最大の欠点は、この Github の問題です。型の null 可能性が尊重されません。これは、必須フィールドに合理的に null を渡す可能性があることを意味するため、かなりイライラする可能性があります。もう 1 つの欠点は、Postgres に特有のものです。詳細については、「移植性」セクションで後ほど説明します。

Prisma recently released TypedSQL — a “a new way to write raw SQL queries in a type-safe way.” They mention that part of the inspiration was both SQLx and PgTyped, so I am excited to try it out!

Something for the Python world: PugSQL

A library I enjoy when I switch to Python is PugSQL (Python). Similar to PgTyped, you create separate SQL files for your queries like this:

-- :name find_email :one
select email from users where user_id = :user_id

which will create a function that you can call:

email = queries.find_email(user_id=42)

The downside (relative to the previous libraries) is these queries aren’t automatically checked for issues. That being said, some tests can surface most (all?) the issues with the query itself — you just need to write them.

If you are feeling fancy, it’s possible to add your own automation which will check the queries. There are ways to verify a query against a DB without running the query — it’s just some additional work. Each query being in its own file makes it a bit easier to automate since you don’t need to go parse out the queries in the first place.

Mark up your interfaces with JDBI

Whenever I talk about how much I liked Dropwizard, I usually get met with blank stares. It’s a bit of a deeper cut in the Java world relative to Spring (either that or normal people don’t discuss Dropwizard at parties).

One of the reasons I liked Dropwizard so much was just because it came with JDBI. That library allowed you to annotate the functions on an interface with SQL queries and it would generate the implementation for you.

public interface UserDAO {
  @SqlQuery("select email from user where user_id = :user_id")
  String fetchEmail(@Bind("user_id") String userId);
}
final UserDAO userDao = database.onDemand(UserDAO.class);

Again though, this would require additional testing to find issues in the queries.

I should also mention that Spring Data JPA does also have the same concept with it’s @Query annotation. It’s been a very long time, but back when I was comparing JDBI and Spring Data JPA - I always felt like Spring was trying to get me to use it’s more magical “function name to sql query” methods. Upon re-reading the docs recently though, I was wrong, and it does mention that you can fallback to @Query pretty frequently.

Other considerations

“Use it sparingly”

If you followed some of the links in this post, you’ll find that some of these libraries don’t advocate for this approach as the primary way to query the database.

TypedSQL describes it as an escape hatch for when querying via their ORM isn’t sufficient. Same for Spring Data JPA which describes it as “fine for a small number of queries”.

This isn’t an unfounded claim — if you go down the path of writing raw SQL for every query, it can be pretty verbose. There are absolutely times where I am making a simple, boring table that’s basically just a key-value store, and the exercise in writing INSERT INTO boring_table VALUES (...) and SELECT * FROM boring_table WHERE ... etc is just a typing exercise.

A library that provides the best of both worlds seems great! The devil is really in the details, as it depends on what you consider to be complex enough to warrant writing raw SQL and how frequently those queries come up.

Portability

One issue with the raw SQL approach is it’s less portable. If you are using an ORM, that ORM often will be compatible with more than just the database you are currently working with.

This can mean small things like running sqlite locally and a different DB in production — or big things like making it easier to migrate your database to something else.

Again, your mileage may vary here — it’s really dependent on how much you care about this.

Use a query builder instead

Going back to the java ecosystem, a popular library is jOOQ. With jOOQ, you aren’t writing raw SQL, but it’s very close:

Libraries for writing raw SQL safely

To me, this is great! My stated goal was just keeping the delta between my code and the generated SQL as little as possible, so query builders like jOOQ or Drizzle do a good job of keeping that delta small.

Not all query builders are made equal here, as I tend to dislike ones like Knex which have a larger delta.

Summary

  • Raw SQL libraries like SQLx, PgTyped, and JDBI allow writing SQL directly while providing safety and type checking.

  • These libraries aim to minimize the gap between code and executed SQL, with some offering benefits like compile-time checking and generated type interfaces.

  • 代わりに、jOOQ や Drizzle などの クエリ ビルダー があり、SQL を直接記述しますが、その差はまだ小さいです。

  • DB ライブラリを選択する際の考慮事項には、移植性、冗長性、複雑なクエリの必要性と単純な CRUD 操作の必要性が含まれます。

以上が生の SQL を安全に作成するためのライブラリの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
Pythonの融合リスト:適切な方法を選択しますPythonの融合リスト:適切な方法を選択しますMay 14, 2025 am 12:11 AM

Tomergelistsinpython、あなたはオペレーター、extendmethod、listcomfulting、olitertools.chain、それぞれの特異的advantages:1)operatorissimplebutlessforlargelist;

Python 3の2つのリストを連結する方法は?Python 3の2つのリストを連結する方法は?May 14, 2025 am 12:09 AM

Python 3では、2つのリストをさまざまな方法で接続できます。1)小さなリストに適したオペレーターを使用しますが、大きなリストには非効率的です。 2)メモリ効率が高い大規模なリストに適した拡張方法を使用しますが、元のリストは変更されます。 3)元のリストを変更せずに、複数のリストをマージするのに適した *オペレーターを使用します。 4)Itertools.chainを使用します。これは、メモリ効率が高い大きなデータセットに適しています。

Python Concatenateリスト文字列Python Concatenateリスト文字列May 14, 2025 am 12:08 AM

Join()メソッドを使用することは、Pythonのリストから文字列を接続する最も効率的な方法です。 1)join()メソッドを使用して、効率的で読みやすくなります。 2)サイクルは、大きなリストに演算子を非効率的に使用します。 3)リスト理解とJoin()の組み合わせは、変換が必要なシナリオに適しています。 4)redoce()メソッドは、他のタイプの削減に適していますが、文字列の連結には非効率的です。完全な文は終了します。

Pythonの実行、それは何ですか?Pythonの実行、それは何ですか?May 14, 2025 am 12:06 AM

pythonexexecutionistheprocessoftransforningpythoncodeintoexecutabletructions.1)interpreterreadSthecode、変換intobytecode、thepythonvirtualmachine(pvm)executes.2)theglobalinterpreeterlock(gil)管理委員会、

Python:重要な機能は何ですかPython:重要な機能は何ですかMay 14, 2025 am 12:02 AM

Pythonの主な機能には次のものがあります。1。構文は簡潔で理解しやすく、初心者に適しています。 2。動的タイプシステム、開発速度の向上。 3。複数のタスクをサポートするリッチ標準ライブラリ。 4.強力なコミュニティとエコシステム、広範なサポートを提供する。 5。スクリプトと迅速なプロトタイピングに適した解釈。 6.さまざまなプログラミングスタイルに適したマルチパラダイムサポート。

Python:コンパイラまたはインタープリター?Python:コンパイラまたはインタープリター?May 13, 2025 am 12:10 AM

Pythonは解釈された言語ですが、コンパイルプロセスも含まれています。 1)Pythonコードは最初にBytecodeにコンパイルされます。 2)ByteCodeは、Python Virtual Machineによって解釈および実行されます。 3)このハイブリッドメカニズムにより、Pythonは柔軟で効率的になりますが、完全にコンパイルされた言語ほど高速ではありません。

ループvs whileループ用のpython:いつ使用するか?ループvs whileループ用のpython:いつ使用するか?May 13, 2025 am 12:07 AM

useaforloopwhenteratingoverasequenceor foraspificnumberoftimes; useawhileloopwhentinuninguntinuntilaConditionismet.forloopsareidealforknownownownownownownoptinuptinuptinuptinuptinutionsituations whileoopsuitsituations withinterminedationations。

Pythonループ:最も一般的なエラーPythonループ:最も一般的なエラーMay 13, 2025 am 12:07 AM

pythonloopscanleadtoErrorslikeinfiniteloops、ModifiningListsDuringiteration、Off-Oneerrors、Zero-dexingissues、およびNestededLoopinefficiencies.toavoidhese:1)use'i

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

MantisBT

MantisBT

Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。