 			try statement.execute()
 		}
 	}
+}
+
+extension Database {
+	/// Executes `stmt` with the *n* parameters in `values` bound to the first *n* SQL parameters of `stmt` and applies `block` to each result row.
+	///
+	/// - parameter sql: The SQL statement to execute
+	/// - parameter values: A sequence of values to bind to SQL parameters
+	/// - parameter block: A closure called for each result row
+	/// - parameter row: A result row of returned data
+	///
+	/// - throws: Any error thrown in `block` or an error if `sql` couldn't be compiled, `values` couldn't be bound, or the statement couldn't be executed
+	public func execute<S: Sequence>(sql: String, parameterValues values: S, _ block: ((_ row: Row) throws -> ())? = nil) throws where S.Iterator.Element == ParameterBindable {
+		let statement = try prepare(sql: sql)
+		try statement.bind(parameterValues: values)
+		if let block = block {
+			try statement.execute(block)
+		}
+		else {
+			try statement.execute()
+		}
+	}
 
 	/// Executes `stmt` with the *n* parameters in `values` bound to the first *n* SQL parameters of `stmt` and applies `block` to each result row.
 	///

	/// - parameter row: A result row of returned data
	///
	/// - throws: Any error thrown in `block` or an error if `sql` couldn't be compiled, `values` couldn't be bound, or the statement couldn't be executed
	public func execute(sql: String, parameterValues values: ParameterBindable?..., _ block: ((_ row: Row) throws -> ())? = nil) throws {
		try execute(sql: sql, parameterValues: values, block)
	}

	/// Executes `stmt` with *value* bound to SQL parameter *name* for each (*name*, *value*) in `parameters` and applies `block` to each result row.

	/// - parameter values: A series of values to bind to SQL parameters
	///
	/// - throws: An error if one of `values` couldn't be bound
	public func bind(parameterValues values: ParameterBindable...) throws  {
		try bind(parameterValues: values)
	}

	/// Binds the *n* parameters in `values` to the first *n* SQL parameters of `self`.
	///
	/// - parameter values: A series of values to bind to SQL parameters
	///
	/// - throws: An error if one of `values` couldn't be bound
	public func bind(parameterValues values: ParameterBindable?...) throws  {
		try bind(parameterValues: values)
	}
}

extension Statement {
	/// Binds the *n* parameters in `values` to the first *n* SQL parameters of `self`.
	///
	/// - parameter values: A series of values to bind to SQL parameters
	///
	/// - throws: An error if one of `values` couldn't be bound
	public func bind(parameterValues values: [ParameterBindable]) throws  {
		var index: Int32 = 1
		for value in values {
			try value.bind(to: stmt, parameter: index)
			index += 1
		}
	}

	/// Binds the *n* parameters in `values` to the first *n* SQL parameters of `self`.
	///
	/// - parameter values: A series of values to bind to SQL parameters
	///
	/// - throws: An error if one of `values` couldn't be bound
	public func bind(parameterValues values: [ParameterBindable?]) throws  {
		var index: Int32 = 1
		for value in values {
			if let value = value {
				try value.bind(to: stmt, parameter: index)
			}
			else {
				guard sqlite3_bind_null(stmt, index) == SQLITE_OK else {
					throw DatabaseError(message: "Error binding null to parameter \(index)", takingDescriptionFromStatement: stmt)
				}
			}
			index += 1
		}
	}

	/// Binds *value* to SQL parameter *name* for each (*name*, *value*) in `parameters`.
	///
	/// - parameter parameters: A sequence of name and value pairs to bind to SQL parameters
	///
	/// - throws: An error if the SQL parameter *name* doesn't exist or *value* couldn't be bound
	public func bind(parameters: [String: ParameterBindable]) throws  {
		for (name, value) in parameters {
			let index = sqlite3_bind_parameter_index(stmt, name)
			guard index > 0 else {
				throw DatabaseError("Unknown parameter \"\(name)\"")
			}
			try value.bind(to: stmt, parameter: index)
		}
	}

	/// Binds *value* to SQL parameter *name* for each (*name*, *value*) in `parameters`.
