How do I use a variable in Postgres scripts?












1















I'm working on a prototype that uses Postgres as its backend. I don't do a lot of SQL, so I'm feeling my way through it. I made a .pgsql file I run with psql that executes each of many files that set up my database, and I use a variable to define the schema that will be used so I can test features without mucking up my "good" instance:



set schema_name 'example_schema'

echo 'The Schema name is' :schema_name

ir sql/file1.pgsql
ir sql/file2.pgsql


This has been working well. I've defined several functions that expand :schema_name properly:



CREATE OR REPLACE FUNCTION :schema_name.get_things_by_category(...


For reasons I can't figure out, this isn't working in my newest function:



CREATE OR REPLACE FUNCTION :schema_name.update_thing_details(_id uuid, _details text)
RETURNS text
LANGUAGE 'plpgsql'
AS $BODY$

BEGIN
UPDATE :schema_name.things
...


The syntax error indicates it's interpreting :schema_name literally after UPDATE instead of expanding it. How do I get it to use the variable value instead of the literal value here? I get that maybe within the BEGIN..END is a different context, but surely there's a way to script this schema name in all places?










share|improve this question





























    1















    I'm working on a prototype that uses Postgres as its backend. I don't do a lot of SQL, so I'm feeling my way through it. I made a .pgsql file I run with psql that executes each of many files that set up my database, and I use a variable to define the schema that will be used so I can test features without mucking up my "good" instance:



    set schema_name 'example_schema'

    echo 'The Schema name is' :schema_name

    ir sql/file1.pgsql
    ir sql/file2.pgsql


    This has been working well. I've defined several functions that expand :schema_name properly:



    CREATE OR REPLACE FUNCTION :schema_name.get_things_by_category(...


    For reasons I can't figure out, this isn't working in my newest function:



    CREATE OR REPLACE FUNCTION :schema_name.update_thing_details(_id uuid, _details text)
    RETURNS text
    LANGUAGE 'plpgsql'
    AS $BODY$

    BEGIN
    UPDATE :schema_name.things
    ...


    The syntax error indicates it's interpreting :schema_name literally after UPDATE instead of expanding it. How do I get it to use the variable value instead of the literal value here? I get that maybe within the BEGIN..END is a different context, but surely there's a way to script this schema name in all places?










    share|improve this question



























      1












      1








      1








      I'm working on a prototype that uses Postgres as its backend. I don't do a lot of SQL, so I'm feeling my way through it. I made a .pgsql file I run with psql that executes each of many files that set up my database, and I use a variable to define the schema that will be used so I can test features without mucking up my "good" instance:



      set schema_name 'example_schema'

      echo 'The Schema name is' :schema_name

      ir sql/file1.pgsql
      ir sql/file2.pgsql


      This has been working well. I've defined several functions that expand :schema_name properly:



      CREATE OR REPLACE FUNCTION :schema_name.get_things_by_category(...


      For reasons I can't figure out, this isn't working in my newest function:



      CREATE OR REPLACE FUNCTION :schema_name.update_thing_details(_id uuid, _details text)
      RETURNS text
      LANGUAGE 'plpgsql'
      AS $BODY$

      BEGIN
      UPDATE :schema_name.things
      ...


      The syntax error indicates it's interpreting :schema_name literally after UPDATE instead of expanding it. How do I get it to use the variable value instead of the literal value here? I get that maybe within the BEGIN..END is a different context, but surely there's a way to script this schema name in all places?










      share|improve this question
















      I'm working on a prototype that uses Postgres as its backend. I don't do a lot of SQL, so I'm feeling my way through it. I made a .pgsql file I run with psql that executes each of many files that set up my database, and I use a variable to define the schema that will be used so I can test features without mucking up my "good" instance:



      set schema_name 'example_schema'

      echo 'The Schema name is' :schema_name

      ir sql/file1.pgsql
      ir sql/file2.pgsql


      This has been working well. I've defined several functions that expand :schema_name properly:



      CREATE OR REPLACE FUNCTION :schema_name.get_things_by_category(...


      For reasons I can't figure out, this isn't working in my newest function:



      CREATE OR REPLACE FUNCTION :schema_name.update_thing_details(_id uuid, _details text)
      RETURNS text
      LANGUAGE 'plpgsql'
      AS $BODY$

      BEGIN
      UPDATE :schema_name.things
      ...


      The syntax error indicates it's interpreting :schema_name literally after UPDATE instead of expanding it. How do I get it to use the variable value instead of the literal value here? I get that maybe within the BEGIN..END is a different context, but surely there's a way to script this schema name in all places?







      postgresql psql variable-expansion






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 20 '18 at 21:27









      Laurenz Albe

      47.6k102748




      47.6k102748










      asked Nov 20 '18 at 16:17









      OwenPOwenP

      17.7k136083




      17.7k136083
























          2 Answers
          2






          active

          oldest

          votes


















          0














          I can think of three approaches, since psql cannot do this directly.



          Shell script



          Use a bash script to perform the variable substitution and pipe the results into psql, like.



          #!/bin/bash

          $schemaName = $1
          $contents = `cat script.sql | sed -e 's/@SCHEMA_NAME@/$schemaName'`

          echo $contents | psql


          This would probably be a lot of boiler plate if you have a lot of .sql scripts.



          Staging Schema



          Keep the approach you have now with a hard-coded schema of something like staging and then have a bash script go and rename staging to whatever you want the actual schema to be.



          Customize the search path



          Your entry point could be an inline script within bash that is piped into psql, does an up-front update of the default connection schema, then uses ir to include all of your .sql files, which should not specify a schema.



          #!/bin/bash

          $schemaName = $1

          psql <<SCRIPT
          SET search_path TO $schemaName;
          ir sql/file1.pgsql
          ir sql/file2.pgsql
          SCRIPT


          Some details: How to select a schema in postgres when using psql?



          Personally I am leaning towards the latter approach as it seems the simplest and most scalable.






          share|improve this answer































            0














            The documentation says:




            Variable interpolation will not be performed within quoted SQL literals and identifiers. Therefore, a construction such as ':foo' doesn't work to produce a quoted literal from a variable's value (and it would be unsafe if it did work, since it wouldn't correctly handle quotes embedded in the value).




            Now the function body is a “dollar-quoted%rdquo; string literal ($BODY$...$BODY$), so the variable will not be replaced there.



            I can't think of a way to do this with psql variables.






            share|improve this answer























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53397197%2fhow-do-i-use-a-variable-in-postgres-scripts%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              0














              I can think of three approaches, since psql cannot do this directly.



              Shell script



              Use a bash script to perform the variable substitution and pipe the results into psql, like.



              #!/bin/bash

              $schemaName = $1
              $contents = `cat script.sql | sed -e 's/@SCHEMA_NAME@/$schemaName'`

              echo $contents | psql


              This would probably be a lot of boiler plate if you have a lot of .sql scripts.



              Staging Schema



              Keep the approach you have now with a hard-coded schema of something like staging and then have a bash script go and rename staging to whatever you want the actual schema to be.



              Customize the search path



              Your entry point could be an inline script within bash that is piped into psql, does an up-front update of the default connection schema, then uses ir to include all of your .sql files, which should not specify a schema.



              #!/bin/bash

              $schemaName = $1

              psql <<SCRIPT
              SET search_path TO $schemaName;
              ir sql/file1.pgsql
              ir sql/file2.pgsql
              SCRIPT


              Some details: How to select a schema in postgres when using psql?



              Personally I am leaning towards the latter approach as it seems the simplest and most scalable.






              share|improve this answer




























                0














                I can think of three approaches, since psql cannot do this directly.



                Shell script



                Use a bash script to perform the variable substitution and pipe the results into psql, like.



                #!/bin/bash

                $schemaName = $1
                $contents = `cat script.sql | sed -e 's/@SCHEMA_NAME@/$schemaName'`

                echo $contents | psql


                This would probably be a lot of boiler plate if you have a lot of .sql scripts.



                Staging Schema



                Keep the approach you have now with a hard-coded schema of something like staging and then have a bash script go and rename staging to whatever you want the actual schema to be.



                Customize the search path



                Your entry point could be an inline script within bash that is piped into psql, does an up-front update of the default connection schema, then uses ir to include all of your .sql files, which should not specify a schema.



                #!/bin/bash

                $schemaName = $1

                psql <<SCRIPT
                SET search_path TO $schemaName;
                ir sql/file1.pgsql
                ir sql/file2.pgsql
                SCRIPT


                Some details: How to select a schema in postgres when using psql?



                Personally I am leaning towards the latter approach as it seems the simplest and most scalable.






                share|improve this answer


























                  0












                  0








                  0







                  I can think of three approaches, since psql cannot do this directly.



                  Shell script



                  Use a bash script to perform the variable substitution and pipe the results into psql, like.



                  #!/bin/bash

                  $schemaName = $1
                  $contents = `cat script.sql | sed -e 's/@SCHEMA_NAME@/$schemaName'`

                  echo $contents | psql


                  This would probably be a lot of boiler plate if you have a lot of .sql scripts.



                  Staging Schema



                  Keep the approach you have now with a hard-coded schema of something like staging and then have a bash script go and rename staging to whatever you want the actual schema to be.



                  Customize the search path



                  Your entry point could be an inline script within bash that is piped into psql, does an up-front update of the default connection schema, then uses ir to include all of your .sql files, which should not specify a schema.



                  #!/bin/bash

                  $schemaName = $1

                  psql <<SCRIPT
                  SET search_path TO $schemaName;
                  ir sql/file1.pgsql
                  ir sql/file2.pgsql
                  SCRIPT


                  Some details: How to select a schema in postgres when using psql?



                  Personally I am leaning towards the latter approach as it seems the simplest and most scalable.






                  share|improve this answer













                  I can think of three approaches, since psql cannot do this directly.



                  Shell script



                  Use a bash script to perform the variable substitution and pipe the results into psql, like.



                  #!/bin/bash

                  $schemaName = $1
                  $contents = `cat script.sql | sed -e 's/@SCHEMA_NAME@/$schemaName'`

                  echo $contents | psql


                  This would probably be a lot of boiler plate if you have a lot of .sql scripts.



                  Staging Schema



                  Keep the approach you have now with a hard-coded schema of something like staging and then have a bash script go and rename staging to whatever you want the actual schema to be.



                  Customize the search path



                  Your entry point could be an inline script within bash that is piped into psql, does an up-front update of the default connection schema, then uses ir to include all of your .sql files, which should not specify a schema.



                  #!/bin/bash

                  $schemaName = $1

                  psql <<SCRIPT
                  SET search_path TO $schemaName;
                  ir sql/file1.pgsql
                  ir sql/file2.pgsql
                  SCRIPT


                  Some details: How to select a schema in postgres when using psql?



                  Personally I am leaning towards the latter approach as it seems the simplest and most scalable.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 21 '18 at 15:19









                  BrandonBrandon

                  7,58521836




                  7,58521836

























                      0














                      The documentation says:




                      Variable interpolation will not be performed within quoted SQL literals and identifiers. Therefore, a construction such as ':foo' doesn't work to produce a quoted literal from a variable's value (and it would be unsafe if it did work, since it wouldn't correctly handle quotes embedded in the value).




                      Now the function body is a “dollar-quoted%rdquo; string literal ($BODY$...$BODY$), so the variable will not be replaced there.



                      I can't think of a way to do this with psql variables.






                      share|improve this answer




























                        0














                        The documentation says:




                        Variable interpolation will not be performed within quoted SQL literals and identifiers. Therefore, a construction such as ':foo' doesn't work to produce a quoted literal from a variable's value (and it would be unsafe if it did work, since it wouldn't correctly handle quotes embedded in the value).




                        Now the function body is a “dollar-quoted%rdquo; string literal ($BODY$...$BODY$), so the variable will not be replaced there.



                        I can't think of a way to do this with psql variables.






                        share|improve this answer


























                          0












                          0








                          0







                          The documentation says:




                          Variable interpolation will not be performed within quoted SQL literals and identifiers. Therefore, a construction such as ':foo' doesn't work to produce a quoted literal from a variable's value (and it would be unsafe if it did work, since it wouldn't correctly handle quotes embedded in the value).




                          Now the function body is a “dollar-quoted%rdquo; string literal ($BODY$...$BODY$), so the variable will not be replaced there.



                          I can't think of a way to do this with psql variables.






                          share|improve this answer













                          The documentation says:




                          Variable interpolation will not be performed within quoted SQL literals and identifiers. Therefore, a construction such as ':foo' doesn't work to produce a quoted literal from a variable's value (and it would be unsafe if it did work, since it wouldn't correctly handle quotes embedded in the value).




                          Now the function body is a “dollar-quoted%rdquo; string literal ($BODY$...$BODY$), so the variable will not be replaced there.



                          I can't think of a way to do this with psql variables.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 20 '18 at 21:26









                          Laurenz AlbeLaurenz Albe

                          47.6k102748




                          47.6k102748






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53397197%2fhow-do-i-use-a-variable-in-postgres-scripts%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

                              How to change which sound is reproduced for terminal bell?

                              Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents