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

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

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

--我们拭目以待!

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

--经测试没有问题!


--下面是测试过程及改进代码
--===================================================
--插入数据除了 id ,其余字段全部以TEXT 格式传递
--modulename 即为表名
--feildname 即为字段名
--feildvalue 即为对应的字段值(插入时全部为text)
--这里的字段名和字段值是一一对应的关系,否则出错
--===================================================
CREATE OR REPLACE FUNCTION f_insert_module_string(
modulename text,
feildname text[],
feildvalue text[],
out returnValue text ) AS $$
DECLARE
myid integer;
ex_result integer default 0;
ex_sql text;
BEGIN
myid:=f_getNewID(modulename,'id');
ex_sql:='insert into '
||quote_ident(moduleName)
||'(id,'
||array_to_string(feildname,',')
||') values('||myid||','''
||array_to_string(feildvalue,''',''')
||''')';
execute ex_sql;
GET DIAGNOSTICS ex_result:= ROW_COUNT;
if ex_result<>0 then returnValue:='{"SUCCESS":"插入操作'||ex_sql||'成功!"}';
else returnValue:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
end if;
END;
$$ language plpgsql; --===================================================
--插入数据除了 id ,其余字段全部以 text格式传递
--modulename 即为表名
--feildname 即为字段名
--feildvalue 即为对应的字段值(插入时全部以int格式)
--这里的字段名和字段值是一一对应的关系,否则出错
--===================================================
CREATE OR REPLACE FUNCTION f_insert_module_string(
modulename text,
feildname text[],
feildvalue text[],
out returnValue text ) AS $$
DECLARE
myid integer;
ex_result integer default 0;
ex_sql text;
BEGIN
myid:=f_getNewID(modulename,'id');
ex_sql:='insert into '
||quote_ident(moduleName)
||'(id,'
||array_to_string(feildname,',')
||') values('||myid||','
||array_to_string(feildvalue,',')
||')';
execute ex_sql;
GET DIAGNOSTICS ex_result:= ROW_COUNT;
if ex_result<>0 then returnValue:='{"SUCCESS":"插入操作'||ex_sql||'成功!"}';
else returnValue:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
end if;
END;
$$ language plpgsql; --===================================================
--以下是合并以上两个过程的代码,但增加了一个类型参数
--主要是为了区分除ID字段外,其他字段的类型
--0: 认为其他字段以text类型插入,即加单引号
--others: 认为其他字段以int类型插入,即没有单引号
--那么问题来了:如果里面有int numeric text交叉怎么办?
--可不可以这样:
-- feildname 顺序打乱(不按表中顺序)
-- 把不用带单引号的字段放前面
-- 需要带引号的放后面
-- 当然feildvalue要分成两个ARRAY了
-- feildname1 text[]不用带单引号的字段值,
-- feildname2 text[]需要带引号的字段值

--我也不知道,我们将继续学习!
--===================================================
--插入数据除了 id ,其余字段全部以 text格式传递
--modulename 即为表名
--feildname 即为字段名
--feildvalue 即为对应的字段值
--inserttype 插入类型 如为0 则插入 text,否则直接插入
--这里的字段名和字段值是一一对应的关系,否则出错--===================================================
CREATE OR REPLACE FUNCTION f_insert_module_string(
modulename text,
feildname text[],
feildvalue text[],
inserttype integer,
out returnValue text ) AS $$
DECLARE
myid integer;
ex_result integer default 0;
ex_sql text;
BEGIN
myid:=f_getNewID(modulename,'id');
ex_sql:='insert into '
||quote_ident(moduleName)
||'(id,'
||array_to_string(feildname,',');
if inserttyp<>0 then
ex_sql:=ex_sql||') values('||myid||','
||array_to_string(feildvalue,',')
||')';
else
ex_sql:=ex_sql||') values('||myid||','''
||array_to_string(feildvalue,''',''')
||''')';
execute ex_sql;
GET DIAGNOSTICS ex_result:= ROW_COUNT;
if ex_result<>0 then returnValue:='{"SUCCESS":"插入操作'||ex_sql||'成功!"}';
else returnValue:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
end if;
END;
$$ language plpgsql; --============================================
--坑永远也填不完,上面完成的挺好的,可是当我用NPGSQL
--parameters.add时发现根本不能传递数组!!
--是的,我用的npgsql 是2.* for .net 4.0
--===========================================
--其实绕了个大弯:
--在f_insert_test中不是用 ARRAY_TO_STRING了吗
--为什么不直接传递一个text类型的字符串过来??
-------------------------------------------
--再来
--===========================================
--C#数据库访问部分:
 public static string ExecuteInsertProcedure(string proName, string tableName, string paramName,  string values, Int32 returnType)
{
string returnValue = string.Empty;
NpgsqlConnection connection = new NpgsqlConnection(getConnectionString());
NpgsqlCommand command = new NpgsqlCommand(proName, connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
SP_SetParam(command, "tablename", NpgsqlDbType.Text, System.Data.ParameterDirection.Input, tableName);
SP_SetParam(command, "feidname",NpgsqlDbType.Text, System.Data.ParameterDirection.Input, paramName);
SP_SetParam(command, "feidvalue", NpgsqlDbType.Text, System.Data.ParameterDirection.Input, values);
SP_SetParam(command, "inserttype", NpgsqlDbType.Integer, System.Data.ParameterDirection.Input, returnType);
SP_SetParam(command, "returnvalue", NpgsqlDbType.Text, System.Data.ParameterDirection.Output, "");
try
{
connection.Open();
command.ExecuteNonQuery();
returnValue = command.Parameters["returnValue"].Value.ToString();
}
catch (NpgsqlException exception)
{
throw new Exception(string.Format("执行SQL【{0}】出错,详细信息为:{1}", proName, exception.Message));
}
finally
{
connection.Close();
}
return returnValue;
}

--C#程序处理部分:
public string insertModule(string tableName, string keys, string values, int returnType)
{
string jsonResult = string.Empty;
if(string.IsNullOrEmpty(tableName)){ jsonResult = "{\"ERROR\":\"请给出需要插入的表名!\"}"; return jsonResult; }
jsonResult = sqlHelper.ExecuteInsertProcedure("f_insert", tableName, keys,values, returnType);
return jsonResult;
}


--plpgsql插入函数再改造如下
--
CREATE OR REPLACE FUNCTION f_insert(
modulename text,
feildname text,
feildvalue text,
inserttype integer,
out returnValue text ) AS $$
DECLARE
myid integer;
ex_result integer default 0;
ex_sql text;
my_feildvalue text[];
BEGIN
myid:=f_getNewID(modulename,'id');
my_feildvalue:=string_to_array(feildvalue,',');
ex_sql:='insert into '
||quote_ident(moduleName)
||'(id,'
||feildname;
if inserttype<>0 then
ex_sql:=ex_sql||') values('||myid||','
||array_to_string(my_feildvalue,',')
||')';
else
ex_sql:=ex_sql||') values('||myid||','''
||array_to_string(my_feildvalue,''',''')
||''')';
end if;
execute ex_sql;
GET DIAGNOSTICS ex_result:= ROW_COUNT;
if ex_result<>0 then returnValue:='{"SUCCESS":"插入操作'||ex_sql||'成功!"}';
else returnValue:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
end if;
END;
$$ language plpgsql;


这样可以了吗? 
是的,可以了!测试通过!
 

干货在这里

--============================================
--既含有需要单引号: date,text,varchar等类型,
--又含不需要单引号的:int,nemeric等类型
--feildname 也要按顺序放
--不需要单引号字段名放前面, feildValue
--需要的放后面 feildsingle
--inserttype=0 :表示所有插入字段不需单引号
-- 1 :表示所有插入字段需要单引号
-- 2 :表示一部分不需单引号,
-- 一部分需要单引号
--===========================================
CREATE OR REPLACE FUNCTION f_insert_all(
modulename text,
feildname text,
feildvalue text,
feildsingle text,
inserttype int,
out returnValue text ) AS $$
DECLARE
myid integer;
ex_result integer default 0;
ex_sql text;
my_feildvalue text[];
BEGIN
myid:=f_getNewID(modulename,'id');
my_feildvalue:=string_to_array(feildvalue,',');
ex_sql:='insert into '
||quote_ident(moduleName)
||'(id,'
||feildname;
if inserttype=0 then
ex_sql:=ex_sql||') values('||myid||','
||array_to_string(my_feildvalue,',')
||')';
else if inserttype=1 then
ex_sql:=ex_sql||') values('||myid||','''
||array_to_string(my_feildvalue,''',''')
||''')';
else
ex_sql:=ex_sql||') values('||myid||','
||array_to_string(my_feildvalue,',');
my_feildvalue:=string_to_array(feildsingle,',');
ex_sql:=ex_sql||','''
||array_to_string(my_feildvalue,''',''')
||''')';
end if;
end if;
execute ex_sql;
GET DIAGNOSTICS ex_result:= ROW_COUNT;
if ex_result<>0 then returnValue:='{"SUCCESS":"插入操作'||ex_sql||'成功!"}';
else returnValue:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
end if;
END;
$$ language plpgsql;

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

最好的永远是下一个:

drop function f_insert_all(text,text);
create or replace function f_insert_all(
table_name text, --表名
insert_feilds text, --需要插入的字段和字段 [{"feild_name":"pt_name","feild_value":"我是中国人"},{"feild_name":"pt_description","feild_value":"我骄傲"}]
out return_value text --返回值
) as $$
declare
ex_sql text;
recs record;
_key text ;
_value text;
ex_result integer;
_maxid integer;
begin
--检查是否插入重复数据,如果重复,返回重复提示
ex_result:=f_insert_check(table_name,insert_feilds);
if ex_result<>0 then
return_value:='{"ERROR":"插入操作失败!请检查是该记录是否已存在!"}';
else
_maxid:=f_getnewid(table_name,'id');
ex_sql:='insert into '||quote_ident(table_name)||'(id';
_value:='('||_maxid; for recs in select * from json_array_elements(insert_feilds::json) loop
ex_sql := ex_sql|| ',' || (recs.value ->> 'feild_name'); --insert feilds
if json_typeof(recs.value -> 'feild_value') ='number' then
_value:=_value||',' ||(recs.value ->> 'feild_value') ; --insert values numeric
else
_value:=_value||','''||(recs.value ->> 'feild_value')||'''' ; --insert values not numeric
end if;
end loop;
ex_sql:=ex_sql||') values'||_value||')';
execute ex_sql;
GET DIAGNOSTICS ex_result:= ROW_COUNT;
if ex_result<>0 then return_value:='{"SUCCESS":"插入操作'||ex_sql||'成功!","id":'||_maxid||'}';
else return_value:='{"ERROR":"插入操作'||ex_sql||'失败!"}';
end if;
--return_value:='{"ERROR":"插入操作'||ex_result||'失败!"}';
end if;
end;
$$ 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. hdu 5730 Shell Necklace —— 分治FFT

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5730 DP式:\( f[i] = \sum\limits_{j=1}^{i} f[i-j] * a[j] ...

  2. JQuery Mobile的页面

    1.JQuery Mobile的页面结构如下图: page:是在浏览器中显示的页面 header:创建页面上方的工具栏(常用于标题和搜索按钮) content:定义了页面的内容,比如文本, 图片,表单 ...

  3. 百度地图API的第一次接触——地图事件

    0.初始化地图 var map = new BMap.Map("container"); var point = new BMap.Point(116.404, 39.915); ...

  4. 推荐几个Laravel 后台管理系统

    小编推荐几个Laravel 后台管理系统 由百牛信息技术bainiu.ltd整理发布于博客园 一.不容错过的Laravel后台管理扩展包 —— Voyager 简介Voyager是一个你不容错过的La ...

  5. SimpliciTI协议地址分配

    1.多个ED节点和AP正确连接后,AP都会给ED分配一个相应的地址.当某个ED出现意外,比如电源问题,和AP断开连接,AP并不将该ED节点的地址消除.当该ED恢复正常,重新申请加入网络时,AP会检测该 ...

  6. sqlServer对内存的管理

    简介 理解SQL Server对于内存的管理是对于SQL Server问题处理和性能调优的基本,本篇文章讲述SQL Server对于内存管理的内存原理. 二级存储(secondary storage) ...

  7. 数据字典生成工具(生成Excel, Word,PDF,html)

    转自:http://www.cnblogs.com/yanweidie/p/3838765.html 数据字典生成工具之旅系列文章导航 数据字典生成工具之旅系列文章导航 宣传语 数据字典生成工具.数据 ...

  8. Java负数的位运算

    /** * 求负数的位运算 *///1. -10 >> 2 = ?//2. -10的原码: 1000 0000 0000 0000 0000 0000 0000 1010 最高位代表符号位 ...

  9. HTML5学习笔记(二)新元素和功能

    <canvas> 新元素(必须使用脚本来绘制图形) 标签 描述 <canvas> 标签定义图形,比如图表和其他图像.该标签基于 JavaScript 的绘图 API HTML5 ...

  10. 利用memoize缓存到Redis出现多个参数同一个结果

    在为后端输出加入Redis缓存的过程中出现的问题. 在我利用Flask-restful架构的后端中,理所当然的利用装饰器marshal_with对我的返回数据进行格式化输出. 举个最简单的例子: fr ...