PostgreSQL抱怨主键中的元素不存在比较函数

PostgreSQL抱怨主键中的元素不存在比较函数,postgresql,psycopg2,postgresql-9.5,Postgresql,Psycopg2,Postgresql 9.5,我在PostgreSQL数据库中有一个表,我想在其中存储以下列: STATION LOCATION SERVICE NORTH EAST text point text real real 每个元组(站点、位置、服务)都是唯一的,所以我决定将其设置为复合类型,并将其设置为主键 但是,当我尝试在数据库中插入一个新条目时,出现以下错误: psycopg2.ProgrammingError:无法识别类型点的比较函数 我猜这是在抱怨你不能

我在
PostgreSQL
数据库中有一个表,我想在其中存储以下列:

STATION   LOCATION    SERVICE    NORTH    EAST
text      point       text       real     real
每个元组
(站点、位置、服务)
都是唯一的,所以我决定将其设置为复合类型,并将其设置为主键

但是,当我尝试在数据库中插入一个新条目时,出现以下错误:
psycopg2.ProgrammingError:无法识别类型点的比较函数

我猜这是在抱怨你不能在二维平面上排列两点,但我看不出这有什么关系。在一个测试示例中,我成功地使用了将点作为主键的复合类型,所以我看不出这有什么不同

我想知道:

  • 为什么会发生这种情况
  • 如何修复它,最好不更改表模式

调试信息: 作为参考,这是我用于插入的代码:

from collections import namedtuple
import psycopg2

DB_NAME = 'testdb'
DB_USER = 'testuser'
DB_HOST = 'localhost'
DB_PASSWORD = '123456'

PVT_TABLE_NAME = 'testtable'

Coordinate = namedtuple('Coordinate', ['lat', 'lon'])

PVT_Error_Key = namedtuple('PVT_Error_Key',
                           ['station', 'location', 'service'])

PVT_Error_Entry = namedtuple(
    'PVT_Error_Entry', ['key', 'north', 'east'])


def _adapt_coordinate(coord):
    """
    Adapter from Python class to Postgre geometric point
    """
    lat = psycopg2.extensions.adapt(coord.lat)
    lon = psycopg2.extensions.adapt(coord.lon)
    return psycopg2.extensions.AsIs("'(%s, %s)'" % (lat, lon))


def _connect_to_db(db_name, db_user, db_host, db_password):
    """
    Connects to a database and returns a cursor object to handle the connection
    """
    connection_str = ('dbname=\'%s\' user=\'%s\' host=\'%s\' password=\'%s\''
                      % (db_name, db_user, db_host, db_password))
    return psycopg2.connect(connection_str).cursor()


def main():
    # Register the adapter for the location
    psycopg2.extensions.register_adapter(Coordinate, _adapt_coordinate)

    cursor = _connect_to_db(DB_NAME, DB_USER, DB_HOST, DB_PASSWORD)

    # Create a dummy entry
    entry = PVT_Error_Entry(
        key=PVT_Error_Key(station='GKIR',
                          location=Coordinate(lat=12, lon=10),
                          service='E1'),
        north=1, east=2)

    # Insert the dummy entry in the database
    cursor.execute(
        'INSERT INTO %s '
        '(KEY, NORTH, EAST) '
        'VALUES((%%s, %%s, %%s), %%s, %%s)'
        % PVT_TABLE_NAME,
        (entry.key.station, entry.key.location, entry.key.service,
         entry.north, entry.east))

    # Retrieve and print all entries of the database
    cursor.execute('SELECT * FROM %s', (PVT_TABLE_NAME))
    rows = cursor.fetchall()
    print(rows)


if __name__ == '__main__':
    main()

不能在主键中使用
point
类型的列,例如:

create table my_table(location point primary key);

ERROR:  data type point has no default operator class for access method "btree"
HINT:  You must specify an operator class for the index or define a default operator class for the data type.
错误消息非常清楚,您需要为该类型创建一个完整的btree运算符类

此答案中描述了完整的程序:


更新。你在评论中提到的解决方法

create table my_table(
    x numeric,
    y numeric,
    primary key (x, y));

insert into my_table values
(1.1, 1.2);
始终可以创建视图,该视图可以像查询表一样进行查询:

create view my_view as
select point(x, y) as location
from my_table;

select *
from my_view;

 location  
-----------
 (1.1,1.2)
(1 row) 

谢谢我想我将把
转换成两个
实数
,在我的例子中,定义所有这些操作符可能是一种过分的做法:)
create view my_view as
select point(x, y) as location
from my_table;

select *
from my_view;

 location  
-----------
 (1.1,1.2)
(1 row)