无法从非对象 Postgres json 数组中提取字段
Cannot extract field from a non-object, Postgres json array
我有一个名为 Stores
的 table,它有一个名为 store_id
的键和一个名为 Sales
的 table,其中包含一个 store_id
引用和一个名为 sales_json
.
的 json 字段
sales_json
看起来像这样:
[{'start_date': '2-20-15', 'end_date': '2-21-15', 'start_time': '11:00 AM',
'end_time': '11:00 PM', 'discount_percentage': 20}, etc]
我有一个 plpgsql 函数,我在其中尝试确定商店当前是否有促销活动,并根据是否为真在结果 table 中存储一个名为 having_sale
的布尔值与否。
我的 SELECT 语句如下所示:
SELECT Stores.store_id,
CASE WHEN (SELECT COUNT(*)
FROM (SELECT *
FROM json_array_elements(sales_json) AS sale
WHERE (now()::date BETWEEN (sale->>'start_date')::date AND
(sale->>'end_date')::date) AND
(now()::time BETWEEN (sale->>'start_time')::time AND
(sale->>'end_time')::time)
) AS current_sales) > 0
THEN TRUE
ELSE FALSE
END) AS having_sale
FROM Stores INNER JOIN Sales
ON Stores.store_id = Sales.store_id;
代码对我来说看起来是正确的,但我收到以下错误:
psycopg2.DataError: cannot extract field from a non-object
我做错了什么,我该如何解决?
错误是由我编写的函数引起的,该函数将 json 数组附加到 sales_json
。我修复了它,现在它看起来像这样:
CREATE OR REPLACE FUNCTION add_sales (insertion_id smallint, new_sales_json json)
RETURNS void AS $$
BEGIN
UPDATE Sales
SET sales_json = array_to_json(ARRAY(SELECT * FROM json_array_elements(sales_json)
UNION ALL SELECT json_array_elements(new_sales_json)))
WHERE store_id = insertion_id;
END;
$$ LANGUAGE plpgsql;
我之前错过了对 new_sales_json 的 json_array_elements()
调用,这就是为什么我在一个数组中获取一个数组,因此出现 cannot extract field from a non-object
错误。
除了你自己整理的,你还可以大大简化你的SELECT
语句:
SELECT store_id
, EXISTS (
SELECT 1
FROM json_array_elements(s.sales_json) sale
WHERE now() BETWEEN (sale->>'start_date')::date + (sale->>'start_time')::time
AND (sale->>'end_date')::date + (sale->>'end_time')::time
) AS having_sale
FROM Stores st
JOIN Sales s USING (store_id);
更短更快。
添加时间和日期会导致 timestamp [without time zone]
。开始存储时间戳数据而不是日期和时间可能是个好主意。
除非,如果您的时间是指每日计划,而不是与日期相结合的绝对界限。那你一定要保持原来的表情。
最后,BETWEEN
包括两个边界,而您通常会 包括 下限,排除 上限:
WHERE now() <b>>=</b> (sale->>'start_date')::date + (sale->>'start_time')::时间
AND now() <b><</b> (sale->>'end_date')::date + (sale->>'end_time')::time
请注意,您的日期和时间是根据时区的当前设置来解释的。
我有一个名为 Stores
的 table,它有一个名为 store_id
的键和一个名为 Sales
的 table,其中包含一个 store_id
引用和一个名为 sales_json
.
sales_json
看起来像这样:
[{'start_date': '2-20-15', 'end_date': '2-21-15', 'start_time': '11:00 AM',
'end_time': '11:00 PM', 'discount_percentage': 20}, etc]
我有一个 plpgsql 函数,我在其中尝试确定商店当前是否有促销活动,并根据是否为真在结果 table 中存储一个名为 having_sale
的布尔值与否。
我的 SELECT 语句如下所示:
SELECT Stores.store_id,
CASE WHEN (SELECT COUNT(*)
FROM (SELECT *
FROM json_array_elements(sales_json) AS sale
WHERE (now()::date BETWEEN (sale->>'start_date')::date AND
(sale->>'end_date')::date) AND
(now()::time BETWEEN (sale->>'start_time')::time AND
(sale->>'end_time')::time)
) AS current_sales) > 0
THEN TRUE
ELSE FALSE
END) AS having_sale
FROM Stores INNER JOIN Sales
ON Stores.store_id = Sales.store_id;
代码对我来说看起来是正确的,但我收到以下错误:
psycopg2.DataError: cannot extract field from a non-object
我做错了什么,我该如何解决?
错误是由我编写的函数引起的,该函数将 json 数组附加到 sales_json
。我修复了它,现在它看起来像这样:
CREATE OR REPLACE FUNCTION add_sales (insertion_id smallint, new_sales_json json)
RETURNS void AS $$
BEGIN
UPDATE Sales
SET sales_json = array_to_json(ARRAY(SELECT * FROM json_array_elements(sales_json)
UNION ALL SELECT json_array_elements(new_sales_json)))
WHERE store_id = insertion_id;
END;
$$ LANGUAGE plpgsql;
我之前错过了对 new_sales_json 的 json_array_elements()
调用,这就是为什么我在一个数组中获取一个数组,因此出现 cannot extract field from a non-object
错误。
除了你自己整理的SELECT
语句:
SELECT store_id
, EXISTS (
SELECT 1
FROM json_array_elements(s.sales_json) sale
WHERE now() BETWEEN (sale->>'start_date')::date + (sale->>'start_time')::time
AND (sale->>'end_date')::date + (sale->>'end_time')::time
) AS having_sale
FROM Stores st
JOIN Sales s USING (store_id);
更短更快。
添加时间和日期会导致 timestamp [without time zone]
。开始存储时间戳数据而不是日期和时间可能是个好主意。
除非,如果您的时间是指每日计划,而不是与日期相结合的绝对界限。那你一定要保持原来的表情。
最后,BETWEEN
包括两个边界,而您通常会 包括 下限,排除 上限:
WHERE now() <b>>=</b> (sale->>'start_date')::date + (sale->>'start_time')::时间
AND now() <b><</b> (sale->>'end_date')::date + (sale->>'end_time')::time
请注意,您的日期和时间是根据时区的当前设置来解释的。