零长度分隔标识符错误在PostgreSQL函数上

huangapple go评论71阅读模式
英文:

Zero length delimited identifier error on postgresql function

问题

I have a table, HVACLoads with JSON columns CoolingLoads and HeatingLoads in PostgreSQL DB. I am just changing the properties of JSON using PostgreSQL JSON functions to update the inner properties by calling the function with migration builder during the Ef Core migration with c#. For example, the data structure for cooling and heating loads is below.

{
  "Roof": {
    "Total": 0,
    "Latent": 23,
    "SensibleTotal": 0,
    "PercentOfTotal": 0,
    "SensibleDelayed": 1,
    "SensibleInstant": 0,
    "SensibleReturnAir": 0
  },
  // ... (other properties)
}

And below is the resulting structure

{
  "Roof": {
    "Total": {
      "scalar": 0,
      "unit": "btuh"
    },
    "Latent": {
      "scalar": 23,
      "unit": "btuh"
    },
    "SensibleTotal": {
      "scalar": 0,
      "unit": "btuh"
    },
    "PercentOfTotal": 0,
    "SensibleDelayed": {
      "scalar": 1,
      "unit": "btuh"
    },
    "SensibleInstant": {
      "scalar": 0,
      "unit": "btuh"
    },
    "SensibleReturnAir": {
      "scalar": 0,
      "unit": "btuh"
    }
  },
  // ... (other properties)
}

I am calling the below PostgreSQL function from migration and trying to update the properties.

protected override void Up(MigrationBuilder migrationBuilder)
{              
    var options = new DbContextOptionsBuilder<APIDbContext>()
                           .UseNpgsql(Startup.Configuration["ConnectionStrings:Postgres"])
                           .Options;
    using var ctx = new APIDbContext(options);
    ctx.Database.OpenConnection(); 

    migrationBuilder.Sql(@"
CREATE OR REPLACE FUNCTION set_loads(object_name text, field_name text)
RETURNS void AS
$$
DECLARE
  query text;
  cooling_power_value numeric;
  heating_power_value numeric;
BEGIN
  IF field_name = 'PercentOfTotal' THEN
    query := 'UPDATE ""HvacLoadReports"" SET ' || field_name || ' = ''' || PercentOfTotal::numeric || ''',
                ""CoolingLoads"" = jsonb_set(""CoolingLoads"", '''{' || object_name || '}'',''' || field_name || '''}''::jsonb, (""CoolingLoads""->>'{' || object_name || '}->>' || field_name || ''')::numeric, false),
                ""HeatingLoads"" = jsonb_set(""HeatingLoads"", '''{' || object_name || '}'',''' || field_name || '''}''::jsonb, (""HeatingLoads""->>'{' || object_name || '}->>' || field_name || ''')::numeric, false)';
  ELSE
    cooling_power_value := (""CoolingLoads""->>'{' || object_name || '}->>'scalar''')::numeric;
    heating_power_value := (""HeatingLoads""->>'{' || object_name || '}->>'scalar''')::numeric;
    query := 'UPDATE ""HvacLoadReports"" SET 
                ""CoolingLoads"" = jsonb_set(""CoolingLoads"", '''{' || object_name || '}'',''' || field_name || '''}''::jsonb, (''{' || cooling_power_value || ',''btuh''}'')::jsonb, true),
                ""HeatingLoads"" = jsonb_set(""HeatingLoads"", '''{' || object_name || '}'',''' || field_name || '''}''::jsonb, (''{' || heating_power_value || ',''btuh''}'')::jsonb, true)';
  END IF;
  EXECUTE query;
END
$$ LANGUAGE plpgsql;
");
   
Calling the above function using the below code inside the migration `Up` method:

```csharp
migrationBuilder.Sql($"SELECT set_loads('{{Roof}}', '{{Total}}');");

But getting an error like

zero-length delimited identifier at or near """"""

Could anyone please point me to why I am getting the above error?

英文:

I have a table, HVACLoads with JSON columns CoolingLoads and HeatingLoadsin PostgreSQL DB. I am just changing the properties of JSON using PostgreSQL JSON functions to update the inner properties by calling the function with migration builder during the Ef Core migration with c#. For example, the data structure for cooling and heating loads is below.

{
  &quot;Roof&quot;: {
    &quot;Total&quot;: 0,
    &quot;Latent&quot;: 23,
    &quot;SensibleTotal&quot;: 0,
    &quot;PercentOfTotal&quot;: 0,
    &quot;SensibleDelayed&quot;: 1,
    &quot;SensibleInstant&quot;: 0,
    &quot;SensibleReturnAir&quot;: 0
  },
  ...
  ....
  
 }

And below is the resulting structure

 {
  &quot;Roof&quot;: {
    &quot;Total&quot;: power { scalar: 0, unit: &quot;btuh&quot;},
    &quot;Latent&quot;:  power { scalar: 23, unit: &quot;btuh&quot;},
    &quot;SensibleTotal&quot;:  power { scalar: 0, unit: &quot;btuh&quot;},
    &quot;PercentOfTotal&quot;: 0,
    &quot;SensibleDelayed&quot;:  power { scalar: 1, unit: &quot;btuh&quot;},
    &quot;SensibleInstant&quot;: power { scalar: 0, unit: &quot;btuh&quot;},
    &quot;SensibleReturnAir&quot;: power { scalar: 0, unit: &quot;btuh&quot;}
  },
  ...
  ....
  
 }

I am calling the below PostgreSQL function from migration and trying to update the properties.

  protected override void Up(MigrationBuilder migrationBuilder)
  {              
        var options = new DbContextOptionsBuilder&lt;APIDbContext&gt;()
                               .UseNpgsql(Startup.Configuration[&quot;ConnectionStrings:Postgres&quot;])
                               .Options;
         using var ctx = new APIDbContext(options);
         ctx.Database.OpenConnection(); 
    
         migrationBuilder.Sql(@&quot;
    CREATE OR REPLACE FUNCTION set_loads(object_name text, field_name text)
RETURNS void AS
$$
DECLARE
  query text;
  cooling_power_value numeric;
  heating_power_value numeric;
BEGIN
  IF field_name = &#39;PercentOfTotal&#39; THEN
    query := &#39;UPDATE &quot;&quot;&quot;&quot;HvacLoadReports&quot;&quot;&quot;&quot;
              SET &#39; || field_name || &#39; = &#39;&#39;&#39; || PercentOfTotal::numeric || &#39;&#39;&#39;,
                  &quot;&quot;&quot;&quot;CoolingLoads&quot;&quot;&quot;&quot; = jsonb_set(&quot;&quot;&quot;&quot;CoolingLoads&quot;&quot;&quot;&quot;, &#39;&#39;{&quot;&quot;&quot;&quot;&#39;&#39;&#39; || object_name || &#39;&#39;&#39;&quot;&quot;&quot;&quot;,&quot;&quot;&quot;&quot;&#39;&#39;&#39; || field_name || &#39;&#39;&#39;&quot;&quot;&quot;&quot;}&#39;&#39;, to_jsonb((&quot;&quot;&quot;&quot;CoolingLoads&quot;&quot;&quot;&quot;-&gt;&gt;&#39;&#39;&quot;&quot;&quot;&quot;&#39; || object_name || &#39;&quot;&quot;&quot;&quot;&#39;&#39;-&gt;&gt;&#39;&#39;&quot;&quot;&quot;&quot;&#39; || field_name || &#39;&quot;&quot;&quot;&quot;&#39;&#39;)::numeric), false),
                  &quot;&quot;&quot;&quot;HeatingLoads&quot;&quot;&quot;&quot; = jsonb_set(&quot;&quot;&quot;&quot;HeatingLoads&quot;&quot;&quot;&quot;, &#39;&#39;{&quot;&quot;&quot;&quot;&#39;&#39;&#39; || object_name || &#39;&#39;&#39;&quot;&quot;&quot;&quot;,&quot;&quot;&quot;&quot;&#39;&#39;&#39; || field_name || &#39;&#39;&#39;&quot;&quot;&quot;&quot;}&#39;&#39;, to_jsonb((&quot;&quot;&quot;&quot;HeatingLoads&quot;&quot;&quot;&quot;-&gt;&gt;&#39;&#39;&quot;&quot;&quot;&quot;&#39; || object_name || &#39;&quot;&quot;&quot;&quot;&#39;&#39;-&gt;&gt;&#39;&#39;&quot;&quot;&quot;&quot;&#39; || field_name || &#39;&quot;&quot;&quot;&quot;&#39;&#39;)::numeric), false)&#39;;
  ELSE
    cooling_power_value := (&quot;&quot;&quot;&quot;CoolingLoads&quot;&quot;&quot;&quot;-&gt;&gt;&#39;&#39;&quot;&quot;&quot;&quot;&#39; || object_name || &#39;&quot;&quot;&quot;&quot;&#39;&#39;,&#39;&#39;&quot;&quot;scalar&quot;&quot;&#39;&#39;)::numeric;
    heating_power_value := (&quot;&quot;&quot;&quot;HeatingLoads&quot;&quot;&quot;&quot;-&gt;&gt;&#39;&#39;&quot;&quot;&quot;&quot;&#39; || object_name || &#39;&quot;&quot;&quot;&quot;&#39;&#39;,&#39;&#39;&quot;&quot;scalar&quot;&quot;&#39;&#39;)::numeric;
    query := &#39;UPDATE &quot;&quot;&quot;&quot;HvacLoadReports&quot;&quot;&quot;&quot;
              SET &quot;&quot;&quot;&quot;CoolingLoads&quot;&quot;&quot;&quot; = jsonb_set(&quot;&quot;&quot;&quot;CoolingLoads&quot;&quot;&quot;&quot;, &#39;&#39;{&quot;&quot;&quot;&quot;&#39;&#39;&#39; || object_name || &#39;&#39;&#39;&quot;&quot;&quot;&quot;,&quot;&quot;&quot;&quot;&#39;&#39;&#39; || field_name || &#39;&#39;&#39;&quot;&quot;&quot;&quot;}&#39;&#39;, to_jsonb((&quot;&quot;&quot;&quot;CoolingLoads&quot;&quot;&quot;&quot;-&gt;&gt;&#39;&#39;&quot;&quot;&quot;&quot;&#39; || object_name || &#39;&quot;&quot;&quot;&quot;&#39;&#39;-&gt;&gt;&#39;&#39;&quot;&quot;&quot;&quot;&#39; || field_name || &#39;&quot;&quot;&quot;&quot;&#39;&#39;)::numeric), false),
                  &quot;&quot;&quot;&quot;HeatingLoads&quot;&quot;&quot;&quot; = jsonb_set(&quot;&quot;&quot;&quot;HeatingLoads&quot;&quot;&quot;&quot;, &#39;&#39;{&quot;&quot;&quot;&quot;&#39;&#39;&#39; || object_name || &#39;&#39;&#39;&quot;&quot;&quot;&quot;,&quot;&quot;&quot;&quot;&#39;&#39;&#39; || field_name || &#39;&#39;&#39;&quot;&quot;&quot;&quot;}&#39;&#39;, to_jsonb((&quot;&quot;&quot;&quot;HeatingLoads&quot;&quot;&quot;&quot;-&gt;&gt;&#39;&#39;&quot;&quot;&quot;&quot;&#39; || object_name || &#39;&quot;&quot;&quot;&quot;&#39;&#39;-&gt;&gt;&#39;&#39;&quot;&quot;&quot;&quot;&#39; || field_name || &#39;&quot;&quot;&quot;&quot;&#39;&#39;)::numeric), false),
                  &quot;&quot;&quot;&quot;CoolingLoads&quot;&quot;&quot;&quot; = jsonb_set(&quot;&quot;&quot;&quot;CoolingLoads&quot;&quot;&quot;&quot;, &#39;&#39;{&quot;&quot;&quot;&quot;&#39;&#39;&#39; || object_name || &#39;&#39;&#39;&quot;&quot;&quot;&quot;,&quot;&quot;&quot;&quot;power&quot;&quot;&quot;&quot;}&#39;&#39;, &#39;&#39;{&quot;&quot;&quot;&quot;scalar&quot;&quot;&quot;&quot;: &#39;&#39; || cooling_power_value || &#39;&#39;, &quot;&quot;&quot;&quot;unit&quot;&quot;&quot;&quot;: &quot;&quot;&quot;&quot;btuh&quot;&quot;&quot;&quot;}&#39;&#39;, true),
                  &quot;&quot;&quot;&quot;HeatingLoads&quot;&quot;&quot;&quot; = jsonb_set(&quot;&quot;&quot;&quot;HeatingLoads&quot;&quot;&quot;&quot;, &#39;&#39;{&quot;&quot;&quot;&quot;&#39;&#39;&#39; || object_name || &#39;&#39;&#39;&quot;&quot;&quot;&quot;,&quot;&quot;&quot;&quot;power&quot;&quot;&quot;&quot;}&#39;&#39;, &#39;&#39;{&quot;&quot;&quot;&quot;scalar&quot;&quot;&quot;&quot;: &#39;&#39; || heating_power_value || &#39;&#39;, &quot;&quot;&quot;&quot;unit&quot;&quot;&quot;&quot;: &quot;&quot;&quot;&quot;btuh&quot;&quot;&quot;&quot;}&#39;&#39;, true)&#39;;
  END IF;
  EXECUTE query;
END
$$ LANGUAGE plpgsql;
&quot;);

Calling the above function using the below code inside the migration Up method:

migrationBuilder.Sql($&quot;SELECT set_loads(&#39;{Roof}&#39;, &#39;{Total}&#39;);&quot;);

But getting an error like

> zero-length delimited identifier at or near """"

Could anyone please point me to why I am getting the above error?

答案1

得分: 0

Looks like you have escaped (doubled up) double-quotes one times too many.
Try this as SQL string in double-quotes:

&quot;
CREATE OR REPLACE FUNCTION set_loads(object_name text, field_name text)
  RETURNS void
  LANGUAGE plpgsql AS
$func$
DECLARE
   query text;
   cooling_power_value numeric;
   heating_power_value numeric;
BEGIN
   IF field_name = &#39;PercentOfTotal&#39; THEN
      query := $q$
         UPDATE &quot;HvacLoadReports&quot;
         SET    &quot;PercentOfTotal&quot; = jsonb_set(&quot;PercentOfTotal&quot;, &#39;Roof&#39;
                              , (SELECT jsonb_object_agg(
                                             key
                                           , CASE WHEN key = &#39;PercentOfTotal&#39;
                                                THEN value
                                                ELSE jsonb_set(&#39;{&quot;power&quot;: {&quot;scalar&quot;: 0, &quot;unit&quot;: &quot;btuh&quot;}}&#39;, &#39;{power, scalar}&#39;, value)
                                             END)
                                 FROM   jsonb_each(&quot;PercentOfTotal&quot; -&gt; &#39;Roof&#39;)))$q$;
   ELSE
      -- ... more
   END IF;

   -- RAISE NOTICE &#39;%&#39;, query;  -- to debug
   EXECUTE query;
END
$func$;
&quot;

I simplified so that all values nested in the key 'Roof' are replaced with the verbose form - except when the key is 'PercentOfTotal'.

Also note the use of dollar-quotes to preserve plain single-quotes. See:

Your life with Postgres is easier with legal, lower-case, unquoted identifiers. See:

英文:

Looks like you have escaped (doubled up) double-quotes one times too many.
Try this as SQL string in double-quotes:

&quot;
CREATE OR REPLACE FUNCTION set_loads(object_name text, field_name text)
  RETURNS void
  LANGUAGE plpgsql AS
$func$
DECLARE
   query text;
   cooling_power_value numeric;
   heating_power_value numeric;
BEGIN
   IF field_name = &#39;PercentOfTotal&#39; THEN
      query := $q$
         UPDATE &quot;&quot;HvacLoadReports&quot;&quot;
         SET    &quot;&quot;PercentOfTota&quot;&quot; = jsonb_set(&quot;&quot;PercentOfTota&quot;&quot;, &#39;Roof&#39;
                              , (SELECT jsonb_object_agg(
                                             key
                                           , CASE WHEN key = &#39;PercentOfTotal&#39;
                                                THEN value
                                                ELSE jsonb_set(&#39;{&quot;&quot;power&quot;&quot;: {&quot;&quot;scalar&quot;&quot;: 0, &quot;&quot;unit&quot;&quot;: &quot;&quot;btuh&quot;&quot;}}&#39;, &#39;{power, scalar}&#39;, value)
                                             END)
                                 FROM   jsonb_each(&quot;&quot;PercentOfTota&quot;&quot; -&gt; &#39;Roof&#39;)))$q$;
   ELSE
      -- ... more
   END IF;

   -- RAISE NOTICE &#39;%&#39;, query;  -- to debug
   EXECUTE query;
END
$func$;
&quot;

I simplified so that all values nested in the key 'Roof' are replaced with the verbose form - except when the key is 'PercentOfTotal'.

Also note the use of dollar-quotes to preserve plain single-quotes. See:

Your life with Postgres is easier with legal, lower-case, unquoted identifiers. See:

huangapple
  • 本文由 发表于 2023年4月17日 06:27:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76030629.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定