2012-06-27 45 views
6

¿Es posible crear una tabla sin una clave principal en SQLAlchemy? La relación quiero definir es el siguiente:SQLAlchemy uno-a-muchos sin que la tabla secundaria tenga una clave principal

class TPost(Base): 
    __tablename__ = "forum_post" 
    id = Column(Integer, primary_key = True) 
    topic_id = Column(Integer, ForeignKey("forum_topic.id")) 
    index = Column(Integer) 
    page = Column(Integer) 
    user_id = Column(Integer, ForeignKey("forum_user.id")) 
    posted_at = Column(DateTime) 
    post_text = Column(String) 
    has_quotes = Column(Boolean) 
    quotes = relationship("TQuote") 

class TQuote(Base): 
    __tablename__ = "forum_quotes" 
    id = Column(Integer, ForeignKey("forum_post.id")) 
    is_direct = Column(Boolean) 
    quoted_text = Column(String) 
    quoted_id = Column(Integer) 

Como se puede ver que realmente no necesita una clave principal, y no tengo la intención de ampliar la relación Quote en el futuro.

Mi problema concreto es representado por este mensaje de error:

sqlalchemy.exc.ArgumentError: Mapper Mapper|TQuote|forum_quotes 
could not assemble any primary key columns for mapped table 'forum_quotes' 

edición: La pareja (id,quoted_id) es único, y presentes en la mayoría de los datos, sin embargo, cuando la cita no es directa (y no tiene un quoted_id en ese caso), inserto el texto entrecomillado directamente en la relación de cita. Podría usar un enfoque de tabla dual (donde las comillas indrect tienen una tabla con una clave principal), pero realmente preferiría implementar esto como una relación de uno a varios. No quiero tener que hacer más de una sola unión.

editar 2:

voy a numerar las cotizaciones y el uso de la clave externa + número generado aplicación como una tecla p, todavía aunque molesto. Ahora para descubrir la sintaxis.

edición 3:

Resuelto el problema que se describe en edición 2. bastante molesto con la alquimia sql ya que tiene toda la información que necesita para implementar el relatioship incluso cuando el modelado de los datos en un nivel alto. Entiendo las razones por las que Sql Alchemy quiere tener una clave principal (hace que el orm sea más fácil de implementar).

Estoy empezando a cuestionar por qué estoy usando Sql Alchemy, sin él podría implementar UPSINT o CREATE_IF_NOT_EXIST de una manera operaciones asincrónicas utilizando psycopg2. Los ORM realmente necesitan ponerse al día.

+2

¿por qué estás tratando de resistir el uso de uno? ¿es el tamaño? limpieza del modelo de datos? ¿otra razon? – van

+0

Limpieza principalmente. Pero si lo piensas incrementado un seeializer es otra operación de base de datos. –

+0

Sí, pero incluso si no define un PK, la base de datos seguirá guardando uno internamente, y ejecutará la misma operación de incremento.El uso de PKs está muy bien optimizado en todos los RDBMS. Busque "claves primarias sustitutas" en Google, y puede llegar a la conclusión de que tener el PK (incluso si no lo necesita) es, de hecho, el más fácil de modelar RDB. Pero lo más importante, no hay nada que guardes al no tenerlo. Por motivos de rendimiento, es posible que desee definir el índice CLUSTED en columnas (id, quoted_id) en lugar de columna PK si busca principalmente en (id, quoted_id). – van

Respuesta

1

Añadir una columna adicional para dar las citas de un índice, y luego añadir una clave compuesta hacer de esta nueva columna + la clave externa.

+0

gracias por compartir su solución – van

13

Supongo que @TokenMacGuy tiene razón, y realmente está confundiendo las nociones de PrimaryKey, y surrogate key. En cuyo caso la respuesta a su pregunta es:

  • NO, SA no admite tablas (y por lo tanto las relaciones a las tablas) sin una clave primaria
  • y NO, no es necesario crear una clave sustituta para cada tabla con el propósito de servir como primary key. Puede definir un PK usando cualquier combinación de columnas con que sea único.

ver el código de abajo para ver un ejemplo:

class TPost(Base): 
    __tablename__ = 'forum_post' 
    id = Column(Integer, primary_key = True) 
    post_text = Column(String) 
    quotes = relationship("TQuote", backref="post") 

class TQuote(Base): 
    __tablename__ = "forum_quotes" 
    id = Column(Integer, ForeignKey("forum_post.id")) 
    is_direct = Column(Boolean) 
    quoted_text = Column(String) 
    quoted_id = Column(Integer) 
    __table_args__ = (PrimaryKeyConstraint(id, quoted_id),) 
+0

Gracias por responder, y he hecho +1 en. '(id, quoted_id)' = candidato si y solo si id_direct = verdadero (el 75% de los datos pertenece a esta categoría). Entonces, para tener una clave candidata para todos los datos, estoy usando un nuevo campo + 'id' nuevo campo es un número incrementado generado por la aplicación. Así que actualiza tu publicación y aceptaré <3 –

+1

Creo que respondí la pregunta tal como se me preguntó y no veo cómo puedo mejorarla. Usted es libre de aceptarlo (o no) con un comentario adicional (que publicó) sobre cómo resolvió el problema. O puede agregar su propia solución y aceptarla para completarla. – van

Cuestiones relacionadas