     /// ``ForeignKeyInfo``. See ``Database/foreignKeys(on:)``.
     public var foreignKeyId: Int
     
+    /// A precise description of the foreign key violation.
+    ///
+    /// For example:
+    ///
+    /// ```
+    /// FOREIGN KEY constraint violation - from player(teamId) to team(id),
+    /// in [id:1 teamId:2 name:"O'Brien" score: 1000]
+    /// ```
+    ///
+    /// See also ``description``.
+    public func failureDescription(_ db: Database) throws -> String {
+        // Grab detailed information, if possible, for better error message
+        let originRow = try originRowID.flatMap { rowid in
+            try Row.fetchOne(db, sql: "SELECT * FROM \(originTable.quotedDatabaseIdentifier) WHERE rowid = \(rowid)")
+        }
+        let foreignKey = try db.foreignKeys(on: originTable).first(where: { foreignKey in
+            foreignKey.id == foreignKeyId
+        })
+        
+        var description: String
+        if let foreignKey = foreignKey {
+            description = """
+                FOREIGN KEY constraint violation - \
+                from \(originTable)(\(foreignKey.originColumns.joined(separator: ", "))) \
+                to \(destinationTable)(\(foreignKey.destinationColumns.joined(separator: ", ")))
+                """
+        } else {
+            description = "FOREIGN KEY constraint violation - from \(originTable) to \(destinationTable)"
+        }
+        
+        if let originRow = originRow {
+            description += ", in \(String(describing: originRow))"
+        } else if let originRowID = originRowID {
+            description += ", in rowid \(originRowID)"
+        }
+        
+        return description
+    }
+    
+    /// Converts the violation into a ``DatabaseError``.
+    ///
+    /// The returned error has the extended code `SQLITE_CONSTRAINT_FOREIGNKEY`.
+    public func databaseError(_ db: Database) -> DatabaseError {
+        // Grab detailed information, if possible, for better error message.
+        // If detailed information is not available, fallback to plain description.
+        let message = (try? failureDescription(db)) ?? String(describing: self)
+        return DatabaseError(
+            resultCode: .SQLITE_CONSTRAINT_FOREIGNKEY,
+            message: message)
+    }
+}
+
+extension ForeignKeyViolation: FetchableRecord {
     public init(row: Row) {
         originTable = row[0]
         originRowID = row[1]
         destinationTable = row[2]
         foreignKeyId = row[3]
     }
-    
+}
+
+extension ForeignKeyViolation: CustomStringConvertible {
     /// A description of the foreign key violation.
     ///
     /// For example:

/// ```
///
/// Related SQLite documentation: <https://www.sqlite.org/pragma.html#pragma_foreign_key_check>
public struct ForeignKeyViolation: FetchableRecord, CustomStringConvertible {
    /// The name of the table that contains the foreign key.
    public var originTable: String
    

                FOREIGN KEY constraint violation - from \(originTable) to \(destinationTable)
                """
        }
    }
}

