본문으로 바로가기 본문 바로가기
WIKI 기술 지식 베이스

D1 Database

원문 보기 위키 갱신

이 문서는 D1Database 바인딩을 사용해 문장을 준비하고, 쿼리를 실행하고, 배치 연산을 하고, Worker에서 D1 데이터베이스를 dump하는 방법을 설명해요.

출처: 문서

본문

Worker에서 D1 데이터베이스와 상호작용하려면 Worker에 제공되는 환경 바인딩(env)을 통해 접근해야 해요.

async fetch(request, env) {
	// D1 database is 'env.DB', where "DB" is the binding name from the Wrangler configuration file.
}
from workers import WorkerEntrypoint

class Default(WorkerEntrypoint):
    async def fetch(self, request):
        # D1 database is 'self.env.DB', where "DB" is the binding name from the Wrangler configuration file.
        pass

D1 바인딩은 D1Database 타입이며, 아래에 나열된 여러 메서드를 지원해요.

메서드 (Methods)

prepare()

나중에 실행될 쿼리 문장을 준비해요.

const someVariable = `Bs Beverages`;
const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(someVariable);
some_variable = "Bs Beverages"
stmt = self.env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(some_variable)
매개변수 (Parameters)
  • query: String 필수
    • 데이터베이스에서 실행하려는 SQL 쿼리예요.
반환 값 (Return values)
안내 (Guidance)

아래처럼 bind 메서드를 사용해 쿼리 문장에 값을 동적으로 바인딩할 수 있어요.

  • bind를 사용하지 않는 정적(static) 문장 예시:

    const stmt = db
    	.prepare("SELECT * FROM Customers WHERE CompanyName = 'Alfreds Futterkiste' AND CustomerId = 1")
    
    stmt = db.prepare("SELECT * FROM Customers WHERE CompanyName = 'Alfreds Futterkiste' AND CustomerId = 1")
    
  • bind를 사용하는 순서 지정(ordered) 문장 예시:

    const stmt = db
    	.prepare("SELECT * FROM Customers WHERE CompanyName = ? AND CustomerId = ?")
    	.bind("Alfreds Futterkiste", 1);
    
    stmt = db.prepare("SELECT * FROM Customers WHERE CompanyName = ? AND CustomerId = ?").bind("Alfreds Futterkiste", 1)
    

자세한 내용은 bind 메서드 문서를 참고하세요.

batch()

여러 SQL 문장을 한 번의 호출로 데이터베이스에 전송해요. 이는 D1까지의 네트워크 왕복으로 인한 지연 시간을 줄여 성능에 큰 영향을 줄 수 있어요. D1은 자동 커밋(auto-commit)으로 동작해요. 구현상 목록의 각 문장이 순차적으로, 동시적이지 않게 실행되고 커밋되는 것이 보장돼요.

배치 문장은 SQL 트랜잭션 ↗︎이에요. 시퀀스의 문장 하나가 실패하면, 해당 문장에 대한 오류가 반환되고 전체 시퀀스가 중단되거나 롤백돼요.

배치 문장을 보내려면 D1Database::batch에 준비된 문장 목록을 제공하면 같은 순서로 결과를 얻을 수 있어요.

const companyName1 = `Bs Beverages`;
const companyName2 = `Around the Horn`;
const stmt = env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`);
const batchResult = await env.DB.batch([
	stmt.bind(companyName1),
	stmt.bind(companyName2)
]);
company_name1 = "Bs Beverages"
company_name2 = "Around the Horn"
stmt = self.env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?")
batch_result = await self.env.DB.batch([
    stmt.bind(company_name1),
    stmt.bind(company_name2),
])
매개변수 (Parameters)
반환 값 (Return values)
  • results: Array
    • D1Database::prepare 문장의 결과를 담은 D1Result 객체들의 배열이에요. 각 객체는 statements 내의 초기 D1Database::prepare 문장의 배열 위치에 대응하는 배열 위치에 있어요.
    • 이 객체에 대한 자세한 내용은 D1Result를 참고하세요.

반환 값 예시 (Example of return values)

const companyName1 = `Bs Beverages`;
const companyName2 = `Around the Horn`;
const stmt = await env.DB.batch([
	env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`).bind(companyName1),
	env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`).bind(companyName2)
]);
return Response.json(stmt)
from workers import Response

company_name1 = "Bs Beverages"
company_name2 = "Around the Horn"
stmt = await self.env.DB.batch([
    self.env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(company_name1),
    self.env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(company_name2),
])
return Response.json(stmt)
[
  {
    "success": true,
    "meta": {
      "served_by": "miniflare.db",
      "duration": 0,
      "changes": 0,
      "last_row_id": 0,
      "changed_db": false,
      "size_after": 8192,
      "rows_read": 4,
      "rows_written": 0
    },
    "results": [
      {
        "CustomerId": 11,
        "CompanyName": "Bs Beverages",
        "ContactName": "Victoria Ashworth"
      },
      {
        "CustomerId": 13,
        "CompanyName": "Bs Beverages",
        "ContactName": "Random Name"
      }
    ]
  },
  {
    "success": true,
    "meta": {
      "served_by": "miniflare.db",
      "duration": 0,
      "changes": 0,
      "last_row_id": 0,
      "changed_db": false,
      "size_after": 8192,
      "rows_read": 4,
      "rows_written": 0
    },
    "results": [
      {
        "CustomerId": 4,
        "CompanyName": "Around the Horn",
        "ContactName": "Thomas Hardy"
      }
    ]
  }
]
console.log(stmt[1].results);
print(stmt[1].results.to_py())
[
  {
    "CustomerId": 4,
    "CompanyName": "Around the Horn",
    "ContactName": "Thomas Hardy"
  }
]
안내 (Guidance)
  • 같은 준비된 문장을 재사용해 배치를 구성할 수 있어요:

    const companyName1 = `Bs Beverages`;
    const companyName2 = `Around the Horn`;
    const stmt = env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`);
    const batchResult = await env.DB.batch([
    	stmt.bind(companyName1),
    	stmt.bind(companyName2)
    ]);
    return Response.json(batchResult);
    
    from workers import Response
    
    company_name1 = "Bs Beverages"
    company_name2 = "Around the Horn"
    stmt = self.env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?")
    batch_result = await self.env.DB.batch([
        stmt.bind(company_name1),
        stmt.bind(company_name2),
    ])
    return Response.json(batch_result)
    

exec()

준비된 문장이나 매개변수 바인딩 없이 하나 이상의 쿼리를 직접 실행해요.

const returnValue = await env.DB.exec(`SELECT * FROM Customers WHERE CompanyName = "Bs Beverages"`);
return_value = await self.env.DB.exec('SELECT * FROM Customers WHERE CompanyName = "Bs Beverages"')
매개변수 (Parameters)
  • query: String 필수
    • 매개변수 바인딩이 없는 SQL 쿼리 문장이에요.
반환 값 (Return values)
  • D1ExecResult: Object
    • count 속성은 실행된 쿼리의 수를 담고 있어요.
    • duration 속성은 밀리초 단위의 작업 지속 시간을 담고 있어요.

반환 값 예시 (Example of return values)

const returnValue = await env.DB.exec(`SELECT * FROM Customers WHERE CompanyName = "Bs Beverages"`);
return Response.json(returnValue);
from workers import Response

return_value = await self.env.DB.exec('SELECT * FROM Customers WHERE CompanyName = "Bs Beverages"')
return Response.json(return_value)
{
  "count": 1,
  "duration": 1
}
안내 (Guidance)
  • 오류가 발생하면 쿼리와 오류 메시지와 함께 예외가 발생하고, 실행이 중지되며 이후 문장은 실행되지 않아요. 자세한 내용은 오류 (Errors)를 참고하세요.
  • 이 메서드는 성능이 더 나쁠 수 있고(어떤 경우에는 준비된 문장을 재사용할 수 있으므로), 더 중요한 것은 안전성이 낮아요.
  • 유지보수와 일회성 작업(예: 마이그레이션 작업)에만 이 메서드를 사용하세요.
  • 입력은 하나 또는 여러 쿼리를 \n으로 구분한 것이 될 수 있어요.

dump

주의 (Caution)

이 API는 D1 알파 기간 동안 만들어진 데이터베이스에서만 동작해요. wrangler d1 info <DATABASE_NAME>으로 데이터베이스가 어떤 버전을 사용하는지 확인하세요.

전체 D1 데이터베이스를 ArrayBuffer 안의 SQLite 호환 파일로 덤프해요.

const dump = await db.dump();
return new Response(dump, {
	status: 200,
	headers: {
		"Content-Type": "application/octet-stream",
	},
});
from workers import Response

dump = await db.dump()
return Response(dump, status=200, headers={"Content-Type": "application/octet-stream"})
매개변수 (Parameters)
  • 없음.
반환 값 (Return values)
  • 없음.

withSession()

반환된 D1DatabaseSession 객체에서 실행되는 쿼리들 간에 순차적 일관성(sequential consistency)을 유지하는 D1 세션을 시작해요.

const session = env.DB.withSession("<parameter>");
session = self.env.DB.withSession("<parameter>")
매개변수 (Parameters)
  • first-primary: String 선택
    • 세션의 첫 번째 쿼리(읽기든 쓰기든)를 primary 데이터베이스 인스턴스로 보내요. 세션을 primary 데이터베이스 인스턴스의 가장 최신 데이터로 시작해야 한다면 이 옵션을 사용하세요.
    • 세션의 이후 쿼리들은 읽기 복제본을 사용할 수 있어요.
    • 세션의 이후 쿼리들은 순차적 일관성을 가져요.
  • first-unconstrained: String 선택
    • 세션의 첫 번째 쿼리(읽기든 쓰기든)를 아무 데이터베이스 인스턴스로 보내요. 세션을 가장 최신 데이터로 시작할 필요가 없고, 세션 시작부터 쿼리 지연 시간 최소화를 우선시하고 싶다면 이 옵션을 사용하세요.
    • 세션의 이후 쿼리들은 순차적 일관성을 가져요.
    • 매개변수가 제공되지 않았을 때의 기본 동작이에요.
  • bookmark: String 선택
    • 이전 D1 세션의 bookmark예요. 이를 통해 제공된 bookmark 이상의 시점부터 새 세션을 시작할 수 있어요.
    • 세션의 이후 쿼리들은 순차적 일관성을 가져요.
반환 값 (Return values)
  • D1DatabaseSession: Object
    • D1Database와 유사하게 prepare()와 batch() 메서드를 포함하고, 추가로 getBookmark 메서드도 포함하는 객체예요.
안내 (Guidance)
  • 읽기 복제를 사용하려면 D1 Sessions API를 사용해야 해요. 그렇지 않으면 모든 쿼리가 계속해서 primary 데이터베이스에서만 실행돼요.
  • session.getBookmark()을 사용해 주어진 세션의 마지막으로 만난 bookmark를 반환할 수 있어요.

D1DatabaseSession 메서드

getBookmark

D1 세션에서 최신 bookmark를 검색해요.

const session = env.DB.withSession("first-primary");
const result = await session
	.prepare(`SELECT * FROM Customers WHERE CompanyName = 'Bs Beverages'`)
	.run()
const { bookmark } = session.getBookmark();
	return bookmark;
session = self.env.DB.withSession("first-primary")
result = await session.prepare(
    "SELECT * FROM Customers WHERE CompanyName = 'Bs Beverages'"
).run()

bookmark = session.getBookmark()
매개변수 (Parameters)
  • 없음
반환 값 (Return values)
  • bookmark: String | null
    • 세션 내에서 마지막으로 실행된 쿼리가 본 데이터베이스의 최신 버전을 식별하는 bookmark예요.
    • 세션 내에서 쿼리가 실행되지 않으면 null을 반환해요.

prepare()

이 메서드는 D1Database::prepare와 동일해요.

batch()

이 메서드는 D1Database::batch와 동일해요.