【问题标题】:Can't insert values using pl\pgSQL procedure无法使用 pl\pgSQL 过程插入值
【发布时间】:2017-12-02 22:21:01
【问题描述】:

我的程序有问题。我们有 2 个表:company 和 typeofcompanies。公司有 3 列 ("companyid","companyname","typeofcompany") ,typeofcompanies 有 2 列 ("typeofcompanyId", "typeofcompany");

这是我将值插入公司的代码:

 CREATE OR REPLACE FUNCTION insert_to_companies(c_name VARCHAR(255),toc INTEGER)
      RETURNS VOID AS $$
          DECLARE i integer;
           BEGIN
          FOR i IN SELECT "typeofcompanyId" FROM typeofcompanies LOOP
            IF toc = i THEN insert into public.companies(companyname, typeofcompany) VALUES (c_name,toc);
              END IF;
          END LOOP;
          IF(SELECT companyname FROM companies WHERE companyname = c_name) = NULL THEN insert into public.typeofcompanies(typeofcompany) VALUES (toc);
                                                                             INSERT into public.companies(companyname,typeofcompany) VALUES (c_name,toc);
          END IF;
          END;
    $$ LANGUAGE plpgsql VOLATILE;

所以如果我们没有 typeofcompany 我们应该创建它。但是当我选择 insert_to_companies("1",5);我采取错误:列“1”不存在。所以我认为这是一个非常容易的问题,但我花了 3 个多小时并没有找到问题。拜托,我需要帮助....

使用 liquibase 创建表的代码

公司:

<databaseChangeLog xmlns = "http://www.liquibase.org/xml/ns/dbchangelog/1.9" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9
                      http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">
    <changeSet id="1" author="tiurinvalery@gmail.com" runOnChange="true" >
        <createTable tableName ="companies">
            <column autoIncrement = "true" name = "companyid" type ="BIGINT">
                <constraints primaryKey ="true"></constraints>
            </column>
            <column name="companyname" type="VARCHAR(255)">
            </column>
            <column name="typeofcompany" type="INTEGER">
            </column>
        </createTable>
    </changeSet>
 </databaseChangeLog>

对于公司类型:

<databaseChangeLog xmlns = "http://www.liquibase.org/xml/ns/dbchangelog/1.9" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9
                      http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd"  >
    <changeSet id="5" author="tiurinvalery@gmail.com" runOnChange="true" >
        <createTable tableName ="typeofcompanies">
            <column autoIncrement = "true" name = "typeofcompanyId" type ="BIGINT">
                <constraints nullable="false" primaryKey="true"></constraints>
            </column>
            <column name = "typeofcompany" type="VARCHAR(255)">
                <constraints nullable="false"></constraints>
            </column>
        </createTable>
    </changeSet>
</databaseChangeLog>

【问题讨论】:

  • 此类问题的最低要求:表定义(CREATE TABLE 显示数据类型和约束的语句)和您的 Postgres 版本。仅仅列出你的列不是很有用。
  • 好吧对不起,我应该用 liquibase 创建我的表,所以这是 liquibase 代码:
  • Liquibase 与问题无关。请显示 SQL 代码。而且我仍然看不到您的 Postgres 版本。 (SELECT version()) 并澄清c_id+"_type" 的来源以及它应该做什么。
  • 我没有用于创建和插入表的 SQL 代码。此代码由 liquibase 库自动生成。(如果有帮助,我可以显示带有列和数据类型的数据库结构的打印屏幕)。 “x86_64-pc-mingw64 上的 PostgreSQL 9.5.9,由 gcc.exe(Rev5,由 MSYS2 项目构建)4.9.2 编译,64 位”。关于 c_id + "_type" - 是的,这是一个逻辑错误,但修复版本后问题仍然存在(我在开始问题中编辑代码)
  • 我无法理解您的要求。

标签: sql postgresql sql-insert plpgsql upsert


【解决方案1】:

表定义可能如下所示:

CREATE TABLE company_type (
   company_type_id serial PRIMARY KEY
 , company_type    text UNIQUE NOT NULL
); 

CREATE TABLE company (
   company_id      serial PRIMARY KEY
 , company         text NOT NULL
 , company_type_id int REFERENCES company_type
);

我做了一些更改:

  • 不使用双引号的 CaMeL 案例名称。如果可以的话,避免这种情况。
  • 对 PK ID 使用 integer 而不是 bigint。我严重怀疑你会用尽本世纪公司类型的关键空间......
  • 仅使用textvarchar(255) 通常是 Postgres 中的一种误解。

最佳功能(或仅查询)很大程度上取决于您的用例。数据库负载、并发性、确切要求。如果可以并发写入,我建议这样做以避免竞争条件:

CREATE OR REPLACE FUNCTION f_insert_to_companies(_c_name text, _toc text)
  RETURNS void AS
$func$
BEGIN
LOOP
   INSERT INTO company(company, company_type_id)
   SELECT _c_name, t.company_type_id
   FROM   company_type t
   WHERE  company_type = _toc;

   EXIT WHEN FOUND;

   -- if type is missing, insert and keep looping    
   INSERT INTO company_type (company_type)
   VALUES (_toc)
   ON     CONFLICT (company_type) DO NOTHING;
END LOOP;
END
$func$ LANGUAGE plpgsql;

dbfiddle here

相关(附详细说明):

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2019-08-24
    相关资源
    最近更新 更多