跳至主要内容

PostgreSQL

PostgreSQL 数据源连接器将 Prisma ORM 连接到 PostgreSQL 数据库服务器。

默认情况下,PostgreSQL 连接器包含一个负责连接到您数据库的数据库驱动程序。您可以使用 驱动程序适配器(预览)使用 Prisma Client 中的 JavaScript 数据库驱动程序连接到您的数据库。

示例

要连接到 PostgreSQL 数据库服务器,您需要在您的 Prisma Schema 中配置一个 datasource

schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

传递给 datasource 块的字段是

  • provider:指定 postgresql 数据源连接器。
  • url:指定 连接 URL 用于 PostgreSQL 数据库服务器。在本例中,一个 环境变量被使用 来提供连接 URL。

使用 node-postgres 驱动程序

截至 v5.4.0,您可以使用 Prisma ORM 与 JavaScript 生态系统中的数据库驱动程序(而不是使用 Prisma ORM 的内置驱动程序)。您可以通过使用 驱动程序适配器 来实现。

对于 PostgreSQL,node-postgrespg)是 JavaScript 生态系统中最受欢迎的驱动程序之一。它可以与通过 TCP 访问的任何 PostgreSQL 数据库一起使用。

本节解释了如何将其与 Prisma ORM 和 @prisma/adapter-pg 驱动程序适配器一起使用。

1. 启用 driverAdapters 预览功能标志

由于驱动程序适配器目前处于 预览 状态,您需要在 Prisma Schema 中的 datasource 块上启用其功能标志

// schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters"]
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

将功能标志添加到您的 Schema 后,重新生成 Prisma Client

npx prisma generate

2. 安装依赖项

接下来,安装 pg 包和 Prisma ORM 的驱动程序适配器

npm install pg
npm install @prisma/adapter-pg

3. 使用驱动程序适配器实例化 Prisma Client

最后,在实例化 Prisma Client 时,您需要将 Prisma ORM 的驱动程序适配器的实例传递给 PrismaClient 构造函数

import { Pool } from 'pg'
import { PrismaPg } from '@prisma/adapter-pg'
import { PrismaClient } from '@prisma/client'

const connectionString = `${process.env.DATABASE_URL}`

const pool = new Pool({ connectionString })
const adapter = new PrismaPg(pool)
const prisma = new PrismaClient({ adapter })

请注意,此代码要求 DATABASE_URL 环境变量设置为您的 PostgreSQL 连接字符串。您可以在下面了解有关连接字符串的更多信息。

注释

指定 PostgreSQL Schema

您可以通过在实例化 PrismaPg 时传递 schema 选项来指定 PostgreSQL Schema

const adapter = new PrismaPg(pool, {
schema: 'myPostgresSchema'
})

连接详细信息

连接 URL

Prisma ORM 遵循 PostgreSQL 官方指南 中指定的连接 URL 格式,但不支持所有参数,并包括其他参数,例如 schema。以下是对 PostgreSQL 连接 URL 所需组件的概述

Structure of the PostgreSQL connection URL

基本 URL 和路径

以下是使用大写字母的占位符值的基本 URL路径结构的示例

postgresql://USER:PASSWORD@HOST:PORT/DATABASE

以下组件构成数据库的基本 URL,它们始终是必需的

名称占位符描述
主机HOST数据库服务器的 IP 地址/域名,例如 localhost
端口PORT数据库服务器运行的端口,例如 5432
用户USER数据库用户的名称,例如 janedoe
密码PASSWORD数据库用户的密码
数据库DATABASE要使用的 数据库 的名称,例如 mydb

参数

连接 URL 也可以接受参数。以下是上面相同的示例,其中三个参数 的占位符值用大写字母表示

postgresql://USER:PASSWORD@HOST:PORT/DATABASE?KEY1=VALUE&KEY2=VALUE&KEY3=VALUE

可以使用以下参数

参数名称必需默认值描述
schemapublic要使用的 schema 的名称,例如 myschema
connection_limitnum_cpus * 2 + 1连接池 的最大大小
connect_timeout5等待打开新连接的最大秒数,0 表示没有超时
pool_timeout10等待池中新连接的最大秒数,0 表示没有超时
sslmodeprefer配置是否使用 TLS。可能的值:preferdisablerequire
sslcert服务器证书的路径。证书路径 相对于 ./prisma 文件夹 解析
sslidentityPKCS12 证书的路径
sslpassword用于保护 PKCS12 文件的密码
sslacceptaccept_invalid_certs配置是否检查证书中缺少的值。可能的值:accept_invalid_certsstrict
host指向包含用于连接的套接字的目录
socket_timeout等待单个查询终止的最大秒数
pgbouncerfalse配置引擎以 启用 PgBouncer 兼容模式
statement_cache_size500自 2.1.0 起:指定每个连接缓存的 准备好的语句 的数量
application_name自 3.3.0 起:为 application_name 配置参数指定一个值
channel_bindingprefer自 4.8.0 起:为 channel_binding 配置参数指定一个值
options自 3.8.0 起:指定在连接启动时发送到服务器的命令行选项

例如,如果您要连接到名为 myschema 的 Schema,将连接池大小设置为 5 并为查询配置 3 秒的超时。您可以使用以下参数

postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=myschema&connection_limit=5&socket_timeout=3

配置 SSL 连接

如果您的数据库服务器使用 SSL,您可以将各种参数添加到连接 URL 中。以下是可能参数的概述

  • sslmode=(disable|prefer|require):
    • prefer(默认):如果可能,优先使用 TLS,接受纯文本连接。
    • disable:不使用 TLS。
    • require:需要 TLS,否则失败。
  • sslcert=<PATH>: 服务器证书的路径。这是数据库服务器用来签署客户端证书的根证书。如果证书不在系统信任的证书存储中,则需要提供此证书。对于 Google Cloud,这可能是 server-ca.pem。证书路径是 相对于 ./prisma 文件夹 解析的
  • sslidentity=<PATH>: 从客户端证书和密钥创建的 PKCS12 证书数据库的路径。这是 PKCS12 格式的 SSL 身份文件,您将使用客户端密钥和客户端证书生成该文件。它将这两个文件合并到一个文件中,并通过密码保护它们(参见下一个参数)。您可以使用以下命令(使用 openssl)使用您的客户端密钥和客户端证书创建此文件
    openssl pkcs12 -export -out client-identity.p12 -inkey client-key.pem -in client-cert.pem
  • sslpassword=<PASSWORD>: 用于保护 PKCS12 文件的密码。在上一步骤中列出的 openssl 命令将在创建 PKCS12 文件时要求输入密码,您需要在这里提供完全相同的密码。
  • sslaccept=(strict|accept_invalid_certs):
    • strict: 证书中任何缺失的值都会导致错误。对于 Google Cloud,特别是如果数据库没有域名,证书可能会缺少域名/IP 地址,导致连接时出现错误。
    • accept_invalid_certs(默认):绕过此检查。请注意此设置的安全后果。

您的数据库连接 URL 将类似于以下内容

postgresql://USER:PASSWORD@HOST:PORT/DATABASE?sslidentity=client-identity.p12&sslpassword=mypassword&sslcert=rootca.cert

通过套接字连接

要通过套接字连接到您的 PostgreSQL 数据库,您必须在连接 URL 中添加一个 host 字段作为查询参数(而不是将其设置为 URI 的 host 部分)。然后,此参数的值必须指向包含套接字的目录,例如:postgresql://USER:PASSWORD@localhost/database?host=/var/run/postgresql/

请注意,localhost 是必需的,值本身会被忽略,可以是任何内容。

注意:您可以在此 GitHub 问题 中找到更多上下文。

PostgreSQL 和 Prisma 模式之间的类型映射

这两个表显示了 PostgreSQL 和 Prisma 模式之间的类型映射。首先是 Prisma ORM 标量类型如何转换为 PostgreSQL 数据库列类型,然后是 PostgreSQL 数据库列类型如何与 Prisma ORM 标量和本机类型相关联

或者,请参阅 Prisma 模式参考 以获取按 Prisma 类型组织的类型映射。

Prisma ORM 标量类型和 PostgreSQL 数据库列类型之间的映射

PostgreSQL 连接器将 Prisma ORM 标量类型 从 Prisma ORM 数据模型 映射到数据库列类型,如下所示

Prisma ORMPostgreSQL
Stringtext
Booleanboolean
Intinteger
BigIntbigint
Floatdouble precision
Decimaldecimal(65,30)
DateTimetimestamp(3)
Jsonjsonb
Bytesbytea

PostgreSQL 数据库列类型到 Prisma ORM 标量和本机类型之间的映射

PostgreSQL(类型 | 别名)支持Prisma ORM本机数据库类型属性注释
bigint | int8✔️BigInt@db.BigInt**BigInt 的默认映射 - 未将类型属性添加到模式中。
boolean | bool✔️Bool@db.Boolean**Bool 的默认映射 - 未将类型属性添加到模式中。
timestamp with time zone | timestamptz✔️DateTime@db.Timestamptz(x)
time without time zone | time✔️DateTime@db.Time(x)
time with time zone | timetz✔️DateTime@db.Timetz(x)
numeric(p,s) | decimal(p,s)✔️Decimal@db.Decimal(x, y)
real | float, float4✔️Float@db.Real
double precision | float8✔️Float@db.DoublePrecision**Float 的默认映射 - 未将类型属性添加到模式中。
smallint | int2✔️Int@db.SmallInt
integer | int, int4✔️Int@db.Int**Int 的默认映射 - 未将类型属性添加到模式中。
smallserial | serial2✔️Int@db.SmallInt @default(autoincrement())
serial | serial4✔️Int@db.Int @default(autoincrement())
bigserial | serial8✔️Int@db.BigInt @default(autoincrement()
character(n) | char(n)✔️String@db.Char(x)
character varying(n) | varchar(n)✔️String@db.VarChar(x)
money✔️Decimal@db.Money
text✔️String@db.Text**String 的默认映射 - 未将类型属性添加到模式中。
timestamp✔️DateTime@db.TimeStamp**DateTime 的默认映射 - 未将类型属性添加到模式中。
date✔️DateTime@db.Date
enum✔️EnumN/A
inet✔️String@db.Inet
bit(n)✔️String@Bit(x)
bit varying(n)✔️String@VarBit
oid✔️Int@db.Oid
uuid✔️String@db.Uuid
json✔️Json@db.Json
jsonb✔️Json@db.JsonB**Json 的默认映射 - 未将类型属性添加到模式中。
bytea✔️Bytes@db.ByteA**Bytes 的默认映射 - 未将类型属性添加到模式中。
xml✔️String@db.Xml
数组类型✔️[]
citext✔️*String@db.Citext* 仅在 启用 Citext 扩展 时可用。
interval尚未不支持
cidr尚未不支持
macaddr尚未不支持
tsvector尚未不支持
tsquery尚未不支持
int4range尚未不支持
int8range尚未不支持
numrange尚未不支持
tsrange尚未不支持
tstzrange尚未不支持
daterange尚未不支持
point尚未不支持
line尚未不支持
lseg尚未不支持
box尚未不支持
path尚未不支持
polygon尚未不支持
circle尚未不支持
复合类型尚未n/a
域类型尚未n/a

内省 将作为 尚未支持 的本机数据库类型添加为 Unsupported 字段

schema.prisma
model Device {
id Int @id @default(autoincrement())
name String
data Unsupported("circle")
}

准备好的语句缓存

一个 准备好的语句 是可以用来优化性能的功能。准备好的语句只解析、编译和优化一次,然后可以多次直接执行,而无需再次解析查询的开销。

通过缓存准备好的语句,Prisma Client 的 查询引擎 不会重复编译相同的查询,从而减少数据库 CPU 使用率和查询延迟。

例如,以下是 Prisma Client 生成的两个不同查询的 SQL 代码

SELECT * FROM user WHERE name = "John";
SELECT * FROM user WHERE name = "Brenda";

参数化后的两个查询将相同,第二个查询可以跳过准备步骤,从而节省数据库 CPU 和一个额外的往返数据库。参数化后的查询

SELECT * FROM user WHERE name = $1

Prisma Client 维持的每个数据库连接都有一个单独的缓存用于存储准备好的语句。可以通过连接字符串中的 statement_cache_size 参数调整此缓存的大小。默认情况下,Prisma Client 每个连接缓存 500 个语句。

由于 pgBouncer 的性质,如果 pgbouncer 参数设置为 true,则会自动为该连接禁用准备好的语句缓存。