2012-03-13 5 views
2

У меня есть таблица, определенная в web2pyсоставного ключа в web2py

db.define_table(
'pairing', 
Field('user',writable=True,readable=True), 
Field('uid', writable=True , readable=True) 
) 

Эта таблица должна иметь пользователь и комбинация UID быть уникальными. Я просмотрел документацию по web2py, но нет прямого способа определить составной ключ. Как определить составной способ в web2py

ответ

9

Это зависит от того, что вы пытаетесь сделать. По умолчанию web2py автоматически создает автоматически увеличивающееся поле id, служащее первичным ключом для каждой таблицы, и это рекомендуется по мере возможности. Если вы имеете дело с унаследованной базой данных с составными первичными ключами и не можете изменить схему, можно указать атрибут primarykey, хотя и с некоторыми ограничениями (как объяснено here):

db.define_table('pairing', 
    Field('user', writable=True, readable=True), 
    Field('uid', writable=True, readable=True), 
    primarykey=['user', 'uid']) 

Возможно, вместо того, чтобы вы на самом деле не нужны настоящий составной первичный ключ, но вам просто нужен способ, чтобы в таблицу были вставлены только уникальные пары значений user/uid. В этом случае, вы можете сделать это, указав правильно сконструированный IS_NOT_IN_DB валидатор для одного из двух полей:

db.define_table('pairing', 
    Field('user', writable=True, readable=True), 
    Field('uid', writable=True, readable=True)) 

db.pairing.uid.requires=IS_NOT_IN_DB(db(db.pairing.user==request.vars.user), 
    'pairing.uid') 

Это удостоверится uid является уникальным среди множества записей, где user соответствует новому значению user существ (поэтому комбинация user и uid должна быть уникальной). Примечание. Валидаторы (например, IS_NOT_IN_DB) применяются только тогда, когда значения вставляются через SQLFORM или с использованием метода .validate_and_insert(), поэтому вышеуказанное не будет работать для произвольных вставок в таблицу, но в первую очередь предназначено для представлений ввода пользователя.

Вы также можете использовать SQL для установки уникального ограничения по нескольким столбцам в таблице (что вы можете делать непосредственно в базе данных или через метод web2py .executesql()). Однако даже при таком ограничении вы все равно хотите выполнить некоторую проверку ввода в своем приложении, чтобы избежать ошибок из базы данных.

+0

У меня есть таблица, где я хотел бы сделать проверку на двух других полях. sh_code и sh_organization. Я пробовал с вашим предлагаемым кодом, но запись все еще вставлена. Любые предложения – Yebach

+0

Трудно сказать, не видя свой код. Вышеупомянутый подход работает с любыми двумя полями. – Anthony

3

Я использую вычисленное поле для создания/моделирования сложного ключа. Возьмем в качестве примера из приведенного выше вопроса, можно определить таблицу перехода следующим образом:

from md5 import md5 
db.define_table('pairing', 
       Field('user', writable=True, readable=True), 
       Field('uid', writable=True, readable=True), 
       Field('user_uid_md5', 
         length=32, 
         unique=True, 
         writable=False, 
         readable=False, 
         compute=lambda row: md5("{0}:{1}".format(row.user,row.uid)).hexdigest())) 

user_uid_md5 поле автоматически вычисляется на вставке и обновлений. Значение этого поля представляет собой хеш md5 строки, полученной из двух полей user и uid. Это поле также обозначено как unique. Таким образом, база данных обеспечивает уникальность здесь, и это работает вокруг ограничения, указанного Anthony. Это также должно работать для эмуляции составных клавиш с более чем двумя полями. Если вы видите какие-либо отверстия в этом подходе, пожалуйста, дайте мне знать.

Редактировать: Небольшое обновление способа вычисления хеша md5 для учетной записи для случая, указанного Chen Levy в комментарии ниже.

+0

Это действительно умный подход; однако я решил использовать встроенную проверку входных данных, чтобы поддерживать стандарт. –

+2

Это _almost_ правильно. Вы также должны учитывать случаи, когда различные комбинации 'user' и' uid' приводятся к одной и той же строке, например.'user = 1' и' uid = 21' против 'user = 12' и' uid = 1'. В этом случае оба будут давать 'md5 ('121')' и будут конфликтовать друг с другом. –

+0

@ChenLevy, хороший момент. Чтобы учесть эту возможность, я немного обновил решение. Дайте мне знать, если у вас возникнут какие-либо проблемы. – crayzeewulf

Смежные вопросы