1. 最近学习postgresql,正一个小活要用上,所以就开始学习了!
    然而,学习的过程极其艰辛,但却也充满了乐趣.
  2.  
  3. 一般来说数据库的操作不外如何增,删,改,查,
    而首要的就是要添加数据到数据库中,因为以前的经验,
    存储过程要比不用存储过程效率要高不少,至少我的程序环境是这样的结果!
  4.  
  5. 所以就想要做写些存储过程,如果一个表一个存储过程,那仅存储过程就得写好几百个
    这个实是有点夸张了!(这还仅是插入.加上删除/修改/查询那得近上千)
  6.  
  7. 那么能不能有个方法,可以减少工作量呢?自动根据表名,字段名及字段值与插入?
    POSTGRESQL 真的很强大!虽然我还没有入门!
  8.  
  9. 这个问题我通过测试看函数花了三整天,总算有点眉目:
    干货直接拉到最后看最后一个插入存储过程.
    下面是我的学习过程,本不想加上,可这是我一步步的做过来的.
  10.  
  11. -- 目标:动态插入表中数据
  12. -- 老规矩上代码
  13. -- 插入函数如下
  14. ----------------------------------------
  15. CREATE OR REPLACE FUNCTION f_insert_module_string(
  16. modulename text,
  17. feildname text[],
  18. feildvalue text[],
  19. out returnValue text ) AS $$
  20. DECLARE
  21. myid integer;
  22. ex_result integer default 0;
  23. ex_sql text;
  24. BEGIN
  25. myid:=f_getNewID(modulename,'id');
  26. ex_sql:='insert into '
  27. ||quote_ident(moduleName)
  28. ||'(id,'
  29. ||array_to_string(feildname,',')
  30. ||') values('||myid||','''
  31. ||array_to_string(feildvalue,''',''')
  32. ||''')';
  33. execute ex_sql;
  34. GET DIAGNOSTICS ex_result:= ROW_COUNT;
  35. if ex_result<>0 then returnValue:='{"SUCCESS":"插入操作'||ex_sql||'成功!"}';
  36. else returnValue:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
  37. end if;
  38. END;
  39. $$ language plpgsql;
  40.  
  41. -- 实际操作
  42. select f_insert_module_string('test','{name,code,gen_time}','{whq,111000,2018-08-20}');
  43. -- 得到如下结果:

--同样,在插入时,直接用单引号把日期给引起来,INSERT 也不会报错,

--那么如果用C#调用存储过程会不会报错呢?

--我们拭目以待!

------------------------------

--经测试没有问题!

  1.  
  1. --下面是测试过程及改进代码
  2. --===================================================
  3. --插入数据除了 id ,其余字段全部以TEXT 格式传递
  4. --modulename 即为表名
  5. --feildname 即为字段名
  6. --feildvalue 即为对应的字段值(插入时全部为text)
  7. --这里的字段名和字段值是一一对应的关系,否则出错
  8. --===================================================
  9. CREATE OR REPLACE FUNCTION f_insert_module_string(
  10. modulename text,
  11. feildname text[],
  12. feildvalue text[],
  13. out returnValue text ) AS $$
  14. DECLARE
  15. myid integer;
  16. ex_result integer default 0;
  17. ex_sql text;
  18. BEGIN
  19. myid:=f_getNewID(modulename,'id');
  20. ex_sql:='insert into '
  21. ||quote_ident(moduleName)
  22. ||'(id,'
  23. ||array_to_string(feildname,',')
  24. ||') values('||myid||','''
  25. ||array_to_string(feildvalue,''',''')
  26. ||''')';
  27. execute ex_sql;
  28. GET DIAGNOSTICS ex_result:= ROW_COUNT;
  29. if ex_result<>0 then returnValue:='{"SUCCESS":"插入操作'||ex_sql||'成功!"}';
  30. else returnValue:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
  31. end if;
  32. END;
  33. $$ language plpgsql;
  34.  
  35. --===================================================
  36. --插入数据除了 id ,其余字段全部以 text格式传递
  37. --modulename 即为表名
  38. --feildname 即为字段名
  39. --feildvalue 即为对应的字段值(插入时全部以int格式)
  40. --这里的字段名和字段值是一一对应的关系,否则出错
  41. --===================================================
  42. CREATE OR REPLACE FUNCTION f_insert_module_string(
  43. modulename text,
  44. feildname text[],
  45. feildvalue text[],
  46. out returnValue text ) AS $$
  47. DECLARE
  48. myid integer;
  49. ex_result integer default 0;
  50. ex_sql text;
  51. BEGIN
  52. myid:=f_getNewID(modulename,'id');
  53. ex_sql:='insert into '
  54. ||quote_ident(moduleName)
  55. ||'(id,'
  56. ||array_to_string(feildname,',')
  57. ||') values('||myid||','
  58. ||array_to_string(feildvalue,',')
  59. ||')';
  60. execute ex_sql;
  61. GET DIAGNOSTICS ex_result:= ROW_COUNT;
  62. if ex_result<>0 then returnValue:='{"SUCCESS":"插入操作'||ex_sql||'成功!"}';
  63. else returnValue:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
  64. end if;
  65. END;
  66. $$ language plpgsql;
  67.  
  68. --===================================================
  69. --以下是合并以上两个过程的代码,但增加了一个类型参数
    --主要是为了区分除ID字段外,其他字段的类型
    --0 认为其他字段以text类型插入,即加单引号
    --others: 认为其他字段以int类型插入,即没有单引号
    --那么问题来了:如果里面有int numeric text交叉怎么办?
    --可不可以这样:
    -- feildname 顺序打乱(不按表中顺序)
    -- 把不用带单引号的字段放前面
    -- 需要带引号的放后面
    -- 当然feildvalue要分成两个ARRAY
    -- feildname1 text[]不用带单引号的字段值,
    -- feildname2 text[]需要带引号的字段值

    --我也不知道,我们将继续学习!
    --===================================================
    --插入数据除了 id ,其余字段全部以 text格式传递
  70. --modulename 即为表名
  71. --feildname 即为字段名
  72. --feildvalue 即为对应的字段值
  73. --inserttype 插入类型 如为0 则插入 text,否则直接插入
  74. --这里的字段名和字段值是一一对应的关系,否则出错--===================================================
  75. CREATE OR REPLACE FUNCTION f_insert_module_string(
  76. modulename text,
  77. feildname text[],
  78. feildvalue text[],
  79. inserttype integer,
  80. out returnValue text ) AS $$
  81. DECLARE
  82. myid integer;
  83. ex_result integer default 0;
  84. ex_sql text;
  85. BEGIN
  86. myid:=f_getNewID(modulename,'id');
  87. ex_sql:='insert into '
  88. ||quote_ident(moduleName)
  89. ||'(id,'
  90. ||array_to_string(feildname,',');
  91. if inserttyp<>0 then
  92. ex_sql:=ex_sql||') values('||myid||','
  93. ||array_to_string(feildvalue,',')
  94. ||')';
  95. else
  96. ex_sql:=ex_sql||') values('||myid||','''
  97. ||array_to_string(feildvalue,''',''')
  98. ||''')';
  99. execute ex_sql;
  100. GET DIAGNOSTICS ex_result:= ROW_COUNT;
  101. if ex_result<>0 then returnValue:='{"SUCCESS":"插入操作'||ex_sql||'成功!"}';
  102. else returnValue:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
  103. end if;
  104. END;
  105. $$ language plpgsql;
  106.  
  107. --============================================
  1. --坑永远也填不完,上面完成的挺好的,可是当我用NPGSQL
    --parameters.add时发现根本不能传递数组!!
    --是的,我用的npgsql 2.* for .net 4.0
    --===========================================
    --其实绕了个大弯:
    --在f_insert_test中不是用 ARRAY_TO_STRING了吗
    --为什么不直接传递一个text类型的字符串过来??
    -------------------------------------------
    --再来
    --===========================================
    --C#数据库访问部分:
  1. public static string ExecuteInsertProcedure(string proName, string tableName, string paramName, string values, Int32 returnType)
  2. {
  3. string returnValue = string.Empty;
  4. NpgsqlConnection connection = new NpgsqlConnection(getConnectionString());
  5. NpgsqlCommand command = new NpgsqlCommand(proName, connection);
  6. command.CommandType = System.Data.CommandType.StoredProcedure;
  7. SP_SetParam(command, "tablename", NpgsqlDbType.Text, System.Data.ParameterDirection.Input, tableName);
  8. SP_SetParam(command, "feidname",NpgsqlDbType.Text, System.Data.ParameterDirection.Input, paramName);
  9. SP_SetParam(command, "feidvalue", NpgsqlDbType.Text, System.Data.ParameterDirection.Input, values);
  10. SP_SetParam(command, "inserttype", NpgsqlDbType.Integer, System.Data.ParameterDirection.Input, returnType);
  11. SP_SetParam(command, "returnvalue", NpgsqlDbType.Text, System.Data.ParameterDirection.Output, "");
  12. try
  13. {
  14. connection.Open();
  15. command.ExecuteNonQuery();
  16. returnValue = command.Parameters["returnValue"].Value.ToString();
  17. }
  18. catch (NpgsqlException exception)
  19. {
  20. throw new Exception(string.Format("执行SQL【{0}】出错,详细信息为:{1}", proName, exception.Message));
  21. }
  22. finally
  23. {
  24. connection.Close();
  25. }
  26. return returnValue;
  27. }
  1.  
  1. --C#程序处理部分:
  1. public string insertModule(string tableName, string keys, string values, int returnType)
  2. {
  3. string jsonResult = string.Empty;
  4. if(string.IsNullOrEmpty(tableName)){ jsonResult = "{\"ERROR\":\"请给出需要插入的表名!\"}"; return jsonResult; }
  5. jsonResult = sqlHelper.ExecuteInsertProcedure("f_insert", tableName, keys,values, returnType);
  6. return jsonResult;
  7. }
  1.  
  1.  
  1. --plpgsql插入函数再改造如下
    --
  1. CREATE OR REPLACE FUNCTION f_insert(
  2. modulename text,
  3. feildname text,
  4. feildvalue text,
  5. inserttype integer,
  6. out returnValue text ) AS $$
  7. DECLARE
  8. myid integer;
  9. ex_result integer default 0;
  10. ex_sql text;
  11. my_feildvalue text[];
  12. BEGIN
  13. myid:=f_getNewID(modulename,'id');
  14. my_feildvalue:=string_to_array(feildvalue,',');
  15. ex_sql:='insert into '
  16. ||quote_ident(moduleName)
  17. ||'(id,'
  18. ||feildname;
  19. if inserttype<>0 then
  20. ex_sql:=ex_sql||') values('||myid||','
  21. ||array_to_string(my_feildvalue,',')
  22. ||')';
  23. else
  24. ex_sql:=ex_sql||') values('||myid||','''
  25. ||array_to_string(my_feildvalue,''',''')
  26. ||''')';
  27. end if;
  28. execute ex_sql;
  29. GET DIAGNOSTICS ex_result:= ROW_COUNT;
  30. if ex_result<>0 then returnValue:='{"SUCCESS":"插入操作'||ex_sql||'成功!"}';
  31. else returnValue:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
  32. end if;
  33. END;
  34. $$ language plpgsql;
  1.  
  1.  
  1. 这样可以了吗? 
    是的,可以了!测试通过!
  1.  

干货在这里

  1. --============================================
  2. --既含有需要单引号: date,text,varchar等类型,
  3. --又含不需要单引号的:int,nemeric等类型
  4. --feildname 也要按顺序放
  5. --不需要单引号字段名放前面, feildValue
  6. --需要的放后面 feildsingle
  7. --inserttype=0 :表示所有插入字段不需单引号
  8. -- 1 :表示所有插入字段需要单引号
  9. -- 2 :表示一部分不需单引号,
  10. -- 一部分需要单引号
  11. --===========================================
  12. CREATE OR REPLACE FUNCTION f_insert_all(
  13. modulename text,
  14. feildname text,
  15. feildvalue text,
  16. feildsingle text,
  17. inserttype int,
  18. out returnValue text ) AS $$
  19. DECLARE
  20. myid integer;
  21. ex_result integer default 0;
  22. ex_sql text;
  23. my_feildvalue text[];
  24. BEGIN
  25. myid:=f_getNewID(modulename,'id');
  26. my_feildvalue:=string_to_array(feildvalue,',');
  27. ex_sql:='insert into '
  28. ||quote_ident(moduleName)
  29. ||'(id,'
  30. ||feildname;
  31. if inserttype=0 then
  32. ex_sql:=ex_sql||') values('||myid||','
  33. ||array_to_string(my_feildvalue,',')
  34. ||')';
  35. else if inserttype=1 then
  36. ex_sql:=ex_sql||') values('||myid||','''
  37. ||array_to_string(my_feildvalue,''',''')
  38. ||''')';
  39. else
  40. ex_sql:=ex_sql||') values('||myid||','
  41. ||array_to_string(my_feildvalue,',');
  42. my_feildvalue:=string_to_array(feildsingle,',');
  43. ex_sql:=ex_sql||','''
  44. ||array_to_string(my_feildvalue,''',''')
  45. ||''')';
  46. end if;
  47. end if;
  48. execute ex_sql;
  49. GET DIAGNOSTICS ex_result:= ROW_COUNT;
  50. if ex_result<>0 then returnValue:='{"SUCCESS":"插入操作'||ex_sql||'成功!"}';
  51. else returnValue:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
  52. end if;
  53. END;
  54. $$ language plpgsql;

怎么样。感觉这个不够好??

最好的永远是下一个:

  1. drop function f_insert_all(text,text);
  2. create or replace function f_insert_all(
  3. table_name text, --表名
  4. insert_feilds text, --需要插入的字段和字段 [{"feild_name":"pt_name","feild_value":"我是中国人"},{"feild_name":"pt_description","feild_value":"我骄傲"}]
  5. out return_value text --返回值
  6. ) as $$
  7. declare
  8. ex_sql text;
  9. recs record;
  10. _key text ;
  11. _value text;
  12. ex_result integer;
  13. _maxid integer;
  14. begin
  15. --检查是否插入重复数据,如果重复,返回重复提示
  16. ex_result:=f_insert_check(table_name,insert_feilds);
  17. if ex_result<>0 then
  18. return_value:='{"ERROR":"插入操作失败!请检查是该记录是否已存在!"}';
  19. else
  20. _maxid:=f_getnewid(table_name,'id');
  21. ex_sql:='insert into '||quote_ident(table_name)||'(id';
  22. _value:='('||_maxid;
  23.  
  24. for recs in select * from json_array_elements(insert_feilds::json) loop
  25. ex_sql := ex_sql|| ',' || (recs.value ->> 'feild_name'); --insert feilds
  26. if json_typeof(recs.value -> 'feild_value') ='number' then
  27. _value:=_value||',' ||(recs.value ->> 'feild_value') ; --insert values numeric
  28. else
  29. _value:=_value||','''||(recs.value ->> 'feild_value')||'''' ; --insert values not numeric
  30. end if;
  31. end loop;
  32. ex_sql:=ex_sql||') values'||_value||')';
  33. execute ex_sql;
  34. GET DIAGNOSTICS ex_result:= ROW_COUNT;
  35. if ex_result<>0 then return_value:='{"SUCCESS":"插入操作'||ex_sql||'成功!","id":'||_maxid||'}';
  36. else return_value:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
  37. end if;
  38. --return_value:='{"ERROR":"插入操作'||ex_result||'失败!"}';
  39. end if;
  40. end;
  41. $$ language plpgsql;

postgresql 存储过程动态插入数据 2的更多相关文章

  1. postgresql 存储过程动态更新数据

    -- 目标:动态更新表中数据 -- 老规矩上代码-----------------------------tablename 表名--feildname 字段名数组--feildvalue 字段值数组 ...

  2. PG数据库创建并执行存储过程批量插入数据

    记录一下PG数据库创建并执行存储过程批量插入数据的SQL: create or replace function addId() returns boolean AS $BODY$ declare i ...

  3. sqlserver存储过程批量插入数据

    在系统中经常会遇到向数据库中批量插入数据情况,存储过程中没有数组,只有通过字符串分割循环插入,下面是一个本人研究的一个例子: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 c ...

  4. mysql应用存储过程批量插入数据

    --批量插入数据的sql语句 delimiter $$ DROP PROCEDURE IF EXISTS `test.sp_insert_batch` $$ CREATE DEFINER =`root ...

  5. mybatis动态插入数据(使用trim标签)

    知识点: 当向一张表里插入数据,传入的参数不固定时,使用到mybatis的动态插入(trim标签) 参考博客:https://blog.csdn.net/h12kjgj/article/details ...

  6. Oracle 存储过程批量插入数据

    oracle 存储过程批量插入大量数据 declare numCount number; userName varchar2(512); email varchar2(512); markCommen ...

  7. mysql利用存储过程批量插入数据

    最近需要测试一下mysql单表数据达到1000W条以上时增删改查的性能.由于没有现成的数据,因此自己构造,本文只是实例,以及简单的介绍. 首先当然是建表: [sql]view plaincopy CR ...

  8. 使用Oracle的存储过程批量插入数据

    原文地址:http://www.cnblogs.com/liaoyu/p/oracle-procedure-batch-insert.html 作者:L君还在说之乎者也 最近在工作中,需要使用生成一些 ...

  9. postgres 使用存储过程批量插入数据

    參考资料(pl/pgsql 官方文档): http://www.postgresql.org/docs/9.3/static/plpgsql.html create or replace functi ...

随机推荐

  1. 单机11g ogg 双向DML复制

    环境说明: Linux为Linux 2.6.32-573.el6.x86_64 Oracle为 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Pr ...

  2. MYSQL学习二 关于左连接

    工作中有如下的SQL, 针对A.ID ='abcdefg', left  join  B和C两个表,来查找其他信息.就算是B和C中没有任何满足条件的记录,最后结果也肯定不是空.因为A.ID ='abc ...

  3. 搭建Android 开发环境(精华)

    http://www.cnblogs.com/xdp-gacl/p/4322165.html 孤傲苍狼 只为成功找方法,不为失败找借口! Android开发学习总结(一)——搭建最新版本的Androi ...

  4. Windows下git的安装与配置

    表示git安装成功.

  5. 11. 几点基于Web日志的Webshell检测思路

    摘要: Web日志记录了网站被访问的情况,在Web安全的应用中,Web日志常被用来进行攻击事件的回溯和取证.Webshell大多由网页脚本语言编写,常被入侵者用作对网站服务器操作的后门程序,网站被植入 ...

  6. Python3 编译中文字串报错解决方案

    问题: Python3.6.5 版本中,程序有中文,运行时出现以下error: SyntaxError: Non-UTF-8 code starting with '\xb2' in file XXX ...

  7. JVM内存GC的骗局

    此文已由作者尧飘海授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 概述 在日常程序开发中,很多JAVA程度员不太关心内存的使用情况.当然,如果程序员运气较好或者系统没有大规模 ...

  8. 3dmax 法线重置

    从一个模型分离部位时,分离出的部分,面法线发生了混乱,左边原始模型,右边分离后 重置法线方法 对模型(比如对分离出的下半身)添加 EditoNormal修改器 选中模型部位 添加Edit Normal ...

  9. 洛谷P3608 [USACO17JAN]Balanced Photo平衡的照片

    P3608 [USACO17JAN]Balanced Photo平衡的照片 题目描述 Farmer John is arranging his NN cows in a line to take a ...

  10. Apache为本地主机配置多个网站根目录详解

    Author:KillerLegend Date:2014.5.27 From:http://blog.csdn.net/killerlegend/article/details/27195445 - ...