1

I want to make a query "If a record within that second and this sensor_id exists, update it with provided new value, else create a record with that value, sensor_id and time".

I managed to create this query:

DO
$do$
BEGIN
IF EXISTS (
   SELECT
      1  
   FROM
      public.measurement_pm2_5  
   WHERE
      measurement_time >= TO_TIMESTAMP('06.07.2016 23:28:43', 'DD.MM.YYYY HH24:MI:SS')  
      AND    measurement_time <  TO_TIMESTAMP('06.07.2016 23:28:44', 'DD.MM.YYYY HH24:MI:SS')  
      AND    sensor_id = 2
) THEN UPDATE
   public.measurement_pm2_5   
SET
   measurement_value = 27  
WHERE
   measurement_time >= TO_TIMESTAMP('06.07.2016 23:28:43', 'DD.MM.YYYY HH24:MI:SS')  
   AND    measurement_time <  TO_TIMESTAMP('06.07.2016 23:28:44', 'DD.MM.YYYY HH24:MI:SS')  
   AND    sensor_id = 2;  
   ELSE INSERT 
   INTO
      public.measurement_pm2_5
      (    sensor_id,    measurement_time,    measurement_value  )  
   VALUES
      (    2,    TO_TIMESTAMP('06.07.2016 23:28:43', 'DD.MM.YYYY HH24:MI:SS'),    27  );  
   END IF;
END;
$do$
LANGUAGE plpgsql;

But it doesn't work as expected.

Query OK, 0 rows affected (execution time: 62 ms; total time: 62 ms)

Although this query:

SELECT
      1  
   FROM
      public.measurement_pm2_5  
   WHERE
      measurement_time >= TO_TIMESTAMP('06.07.2016 23:28:43', 'DD.MM.YYYY HH24:MI:SS')  
      AND    measurement_time <  TO_TIMESTAMP('06.07.2016 23:28:44', 'DD.MM.YYYY HH24:MI:SS')  
      AND    sensor_id = 2

returns one record, the UPDATE part of the first query doesn't look to be executed.

I'm using PostgreSQL 9.5.

What am I doing wrong?

Edit:

measurement_pm2_5 table:

CREATE TABLE public.measurement_pm2_5 (
  sensor_id SERIAL,
  measurement_time TIMESTAMP WITHOUT TIME ZONE NOT NULL,
  measurement_value NUMERIC(6,2) NOT NULL,
  CONSTRAINT measurement_pm2_5_sensor_id_fkey FOREIGN KEY (sensor_id)
    REFERENCES public.sensor(id)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION
    NOT DEFERRABLE
) 
WITH (oids = false);
5
  • What are your datatypes? I tested it with CREATE TABLE measurement_pm2_5 ( measurement_time timestamp NOT NULL, sensor_id integer NOT NULL DEFAULT 1, measurement_value integer NOT NULL DEFAULT 1 ) WITHOUT OIDS; and it works as expected. Commented Aug 27, 2016 at 16:34
  • I updated my question. Commented Aug 27, 2016 at 16:41
  • Why do you think that the row was not updated? What client software you are using for test the query? do statement does not return any useful information itself (except when error occurred). Just change your update statement to UPDATE public.measurement_pm2_5 SET measurement_value = measurement_value + 0.01 ... for example to ensure that all Ok (or not). Commented Aug 27, 2016 at 18:13
  • Oh... you're right! It's actually working :D The "SQL Manager Lite for PostgreSQL" is a liar! I feel embarrassed... Commented Aug 27, 2016 at 18:39
  • That's the spirit! :) Commented Aug 27, 2016 at 18:52

1 Answer 1

1

From your SQL code it is easy to tell that you are experienced in procedural programming languages. PL/pgSQL requires a different mindset though. Carefully read the docs on PL/pgSQL programming and start thinking in sets and operations that succeed or fail. This is not at all meant to belittle you; take it as well-intended advice from a fellow programmer who has seen both sides of the fence.

In this case, simply try the UPDATE and if it fails, do an INSERT instead.

DO $do$
DECLARE
    obs timestamp := to_timestamp('06.07.2016 23:28:43', 'DD.MM.YYYY HH24:MI:SS');
BEGIN
    UPDATE public.measurement_pm2_5   
    SET measurement_value = 27  
    WHERE measurement_time = date_trunc('second', obs)
    AND   sensor_id = 2;

    IF NOT FOUND THEN   
        INSERT INTO public.measurement_pm2_5
               (sensor_id, measurement_time, measurement_value)  
        VALUES (2, obs, 27);  
    END IF;
END;
$do$ LANGUAGE plpgsql;
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your answer. The query looks much clearer than mine but it still doesn't work. It's obvious that I'm doing something wrong, but I have no idea what. It's weird that SELECT (second query in my question) returns a record but the provided query affects 0 rows.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.