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)