skynet 创建存储过程脚本

最近主程更改了数据库的操作方案,由之前的拼写sql脚本转为在mysql端创建好存储过程后,直接调用存储过程。

首先对一个表测试上述过程:

数据库端存储过程:(测试表)

CREATE TABLE `randomval` (
  `id` int(10) unsigned NOT NULL,
  `val` int(10) unsigned NOT NULL,
  `step` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

创建存储过程:

DELIMITER $$

  CREATE DEFINER=`root`@`%` PROCEDURE `qy_insert_randomval`(IN in_id int, IN in_val int, IN in_step int)
  BEGIN 
    insert into randomval (`id`, `val`, `step`) values (in_id, in_val, in_step)
    on duplicate key update `id` = in_id, `val` = in_val, `step` = in_step;
  END $$

  DELIMITER;

skynet的连接:更改的test下的testmysql.lua

skynet.start(function()
    local function on_connect(db)
        db:query("set charset utf8");
    end
    local db=mysql.connect({
        host="127.0.0.1"或"局域网ip",
        port=3306,
        database="XXXX",
        user="XXXX",
        password="XXXX",
        max_packet_size = 1024 * 1024,
        on_connect = on_connect
    })    
           
    if not db then
        print("failed to connect")
    end
    --拼接调用存储过程的sql语句
    print("testmysql success to connect to mysql server")

  --表t的格式忽略,和项目有关,可自定义
    local t = {__fields = {id = 34, val = 30, step = 50}, __tname = "randomval", __head_ord = {"id", "val", "step"} }
    local tmp_sql = {}
        local sql_first_part = string.format("call " .. "qy_insert_" .. t.__tname .. "(" )
        table.insert(tmp_sql, sql_first_part)
           
        assert(nil ~= t.__head_ord)
        local counter = 0
        for k, v in ipairs(t.__head_ord) do
            print(k, v)  
            assert(nil ~= t.__fields[v])
            if counter > 0 then
                table.insert(tmp_sql, ", ")
            else
                counter = counter + 1
            end
                
            if type(t.__fields[v]) == "string" then
                table.insert(tmp_sql, string.format("‘%s‘",t.__fields[v] ))
            else
                table.insert(tmp_sql, string.format("%s", t.__fields[v]))
            end
        end

table.insert(tmp_sql, ")")    
        print("sql is :", table.concat(tmp_sql))
        db:query(table.concat(tmp_sql))

--db:disconnect()
    --skynet.exit()                    
end)                

这时表,存储过程都创建好了,运行testmysql脚本: ./skynet ./examples/config.mysql

成功调用存储过程并插入一条记录. 

由于主程要求每个表都要有一个“插入不成功就更新的存储过程”,虽说用了navicat,但是目前对它的了解,只能一个一个的创建,很麻烦;

要不就是执行一个创建所有过程的sql脚本,用navicat执行创建。于是选择了后者。

首先提取共性,需要以下:

(1) 统一命名为"qy_insert_" + "表名"的格式 

(2) 获取需要创建存储过程的表名,表的每个字段名,字段类型(TABLE_TYPE)和 字段的值类型 (DATA_TYPE)

以下是实现:

  local addr = io.open("./user_sqlscript.sql", "w")
    assert(addr)
    local sql = "select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = " .. ‘"‘ .. "数据库名称" .. ‘"‘ //到这里选出的是数据库中所有的表。加上后面是筛选需要的表 .. "and TABLE_NAME NOT like" .. "‘" .. "g_%" .. "‘";

  print(sql)
    local table_list = db:query(sql)
--[[

  DELIMITER $$

  CREATE DEFINER=`root`@`%` PROCEDURE `qy_insert_randomval`(IN in_id int, IN in_val int, IN in_step int)
  BEGIN 
    insert into randomval (`id`, `val`, `step`) values (in_id, in_val, in_step)
    on duplicate key update `id` = in_id, `val` = in_val, `step` = in_step;
  END $$

  DELIMITER;

  以此存储过程为例

--]]
    for k, v in ipairs(table_list) do
        local script =  {}
        local tmpsql1 = {} -- 存储 `qy_insert_randomval`(IN in_id int, IN in_val int, IN in_step int)中的 “IN in_id int, IN in_val int, IN in_step int”
        local tmpsql2 = {} --存储 insert into randomval (`id`, `val`, `step`) 中的 “`id`, `val`, `step`”
        local tmpsql3 = {} --存储 values (in_id, in_val, in_step) 中的 “in_id, in_val, in_step”
        local tmpsql4 = {} --存储 on duplicate key update `id` = in_id, `val` = in_val, `step` = in_step; 中的  “`id` = in_id, `val` = in_val, `step` = in_step”

local sql = string.format("select COLUMN_NAME , DATA_TYPE , COLUMN_TYPE from information_schema.`COLUMNS` where table_name = " .. ‘"‘ .. "%s" .. ‘";‘, v.TABLE_NAME)

    --COLUMN_NAME 是列名, COLUMN_TYPE 是列的类型如(varchar,int(6)unsigned)等,DATA_TYPE是该列的值类型(int, varchar)等
        print(sql)                     
        local col_val = db:query(sql)  
        assert(col_val)                 
        for k, v in ipairs(col_val) do
            for sk, sv in pairs(v) do  
                if sv == "int" then
                    print("string is ")
                end                      
            end                        
        end                            
                        
        --format each percudure part   
        local idx = 0                       
        for sk, sv in ipairs(col_val) do
            if idx > 0 then             
                table.insert(tmpsql1, ", ")
                table.insert(tmpsql2, ", ")
                table.insert(tmpsql3, ", ")
                table.insert(tmpsql4, ", ")
            else
                idx = 1
            end
            
            if sv.DATA_TYPE == "varchar" then
                table.insert(tmpsql1, string.format("IN %s %s", "in_" .. sv.COLUMN_NAME, sv.COLUMN_TYPE))
            else
                table.insert(tmpsql1, string.format("IN %s %s", "in_" .. sv.COLUMN_NAME, sv.DATA_TYPE))
            end

table.insert(tmpsql2, string.format("`%s`", sv.COLUMN_NAME))
            table.insert(tmpsql3, string.format("in_%s", sv.COLUMN_NAME))
            table.insert(tmpsql4, string.format("`%s` = in_%s", sv.COLUMN_NAME, sv.COLUMN_NAME))
        end
        
        table.insert(tmpsql1, ")\n")
        table.insert(tmpsql2, ")")
        table.insert(tmpsql3, ")\n")
        table.insert(tmpsql4, ";\n")

--chain all tmpsqlx up
        table.insert(script, "DELIMITER $$\n")
        table.insert(script, string.format("CREATE DEFINER=`root`@`%%` PROCEDURE `%s`(", "qy_insert_" .. v.TABLE_NAME))
        table.insert(script, table.concat(tmpsql1))
        table.insert(script, "BEGIN \n")
        table.insert(script, string.format("insert into %s (%s values (%s", v.TABLE_NAME, table.concat(tmpsql2), table.concat(tmpsql3)))
        table.insert(script, string.format("on duplicate key update %s", table.concat(tmpsql4)))
        table.insert(script, "END$$ \n")
        table.insert(script, "DELIMITER ;")
        local percudure = table.concat(script)
        print(percudure)

addr:write(percudure)
        addr:write("\n\n")
    end
    addr:close() --打开文件别忘了关闭

以上代码实现了一个从数据库中查询出所有的表及其列名,列的类型,然后拼装成每个表需要的存储过程。

前面说到用到的工具是navicate当用工具创建存储过程时:function->procedure->输入参数-> 直接在BEGIN,END中间写过程。

而且用此方法创建时,得到的存储过程代码是没有下面的内容的

DELIMITER

...

...

END $$

DELIMITER;

因此,一开始没有意识到此问题,我直接将生成的sql文件用navicate生成存储过程时是有问题的,总是说存储过程有问题,但是对比用navicat直接生成的代码,又是一模一样的。因此很郁闷。

网上搜资料找到要加上上面的内容,然后生成成功.

原因在这篇文章中叙述的挺详细的:

http://blog.sina.com.cn/s/blog_4c197d420101d3oa.html

------------------------------分割线------------------------------

skynet中庸存储过程查询数据库并接受返回值时可以这样使用:

db:query(“call 存储过程名(@a,@b, @c)”)

local r = db:query("SELECT @a, @b, @c")

注:传出变量为@a,@b,@c ,切@a之间没有空格

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

由于数据库基础不是很好,还没找到好的方法实现调用存储过程返回数据集的操作,望各位赐教!

以后补充.

时间: 2024-10-27 14:13:56

skynet 创建存储过程脚本的相关文章

skynet 创建 lua 服务流程

本文以 skynet 示例 simpledb 为例,讲述 skynet 创建 lua 服务的流程 首先 skynet 中使用 skynet.newservice 来创建 lua 服务 1 skynet.newservice("simpledb") 1 --@name:"simpledb" 2 --@args: nil 3 function skynet.newservice(name, ...) 4 return skynet.call(".launche

存储过程一个简单编写样式与为什么创建存储过程时不执行操作的原因

今天我接收到一个任务就是创建一个数据脚本再原来8万条数据的基础上插入剩下的数据,总共数据为2千万条.之前是创建一个文本文件,进行上传导入数据的,但这个导入数据的时是要有6个月的时间跨度,那么上传一天一个文本,那就要创建180个文本文件,那是得不偿失的.因此想到了数据脚本写存储过程. 这是我简单插入数据,并根据一定的数量进行时间累加的存储过程脚本: USE [eRAS]GO /****** Object:  StoredProcedure [dbo].[AddSrcCCAUTH]    Scrip

经典实用的自动创建Bash脚本文件头的脚本

今天给大家展示一下,我自己写的一个自动创建Bash脚本文件头的脚本(名为create),希望能对初学脚本者带来一定的思维提示.毕竟对于一个经常写脚本的运维人员来说,每次写脚本的时候都需要重复的去写一遍文件头,也是一件很累赘的事情,既然我们学了脚本,为什么不让它来为我们减轻一下负担了.所以一个自动创建Bash脚本文件头的想法在我脑海里面产生了. 本脚本所需要实现的功能: 1,能够自动创建一个标准的Bash脚本文件头,带有详细注释信息 2,能够给新建完成的Bash脚本文件自动添加执行权限 [[ema

SQL创建表脚本

<1>SQL Server设置主键自增长列 SQL Server设置主键自增长列 1.新建一数据表,里面有字段id,将id设为为主键 www.2cto.com create table tb(id int,constraint pkid primary key (id)) create table tb(id int primary key ) 2.新建一数据表,里面有字段id,将id设为主键且自动编号 create table tb(id int identity(1,1),constrai

MySql中创建存储过程

MySQL 存储过程是从 MySQL 5.0 开始增加的新功能.存储过程的优点有一箩筐.不过最主要的还是执行效率和SQL 代码封装.特别是 SQL 代码封装功能,如果没有存储过程,在外部程序访问数据库时(例如 PHP),要组织很多 SQL 语句.特别是业务逻辑复杂的时候,一大堆的 SQL 和条件夹杂在 PHP 代码中,让人不寒而栗.现在有了 MySQL 存储过程,业务逻辑可以封装存储过程中,这样不仅容易维护,而且执行效率也高. 一.MySQL 创建存储过程 "pr_add" 是个简单的

MySQL创建存储过程

存储过程和函数的区别参考链接: http://www.cnblogs.com/lengbingshy/archive/2010/02/25/1673476.html 创建存储过程: DROP PROCEDURE mypro;CREATE procedure mypro (sid INT,OUT sCount INT)BEGIN SELECT COUNT(*) INTO sCount from student where id = sid;END 执行该存储过程: CALL mypro(1,@c)

[转]MYSQL 创建存储过程

MySQL 存储过程是从 MySQL 5.0 开始增加的新功能.存储过程的优点有一箩筐.不过最主要的还是执行效率和SQL 代码封装.特别是 SQL 代码封装功能,如果没有存储过程,在外部程序访问数据库时(例如 PHP),要组织很多 SQL 语句.特别是业务逻辑复杂的时候,一大堆的 SQL 和条件夹杂在 PHP 代码中,让人不寒而栗.现在有了 MySQL 存储过程,业务逻辑可以封装存储过程中,这样不仅容易维护,而且执行效率也高. 一.MySQL 创建存储过程 "pr_add" 是个简单的

Exchange 2013 PowerShell创建自定义脚本

我们可以通过执行单条命令或者结合管道运行多条命令来完成很多任务,但是有时你想创建一个脚本,执行一系列的操作或者加载一个函数库或者预定义变量或别名在Shell中,这一节,我们将学习创建脚本以及运行脚本 怎么做呢? 1.  让我们创建一个基本的脚本,来自动执行一个多步骤的过程.启用文本编辑器,输入如下代码: param( $name, $maxsendsize, $maxreceivesize, $city, $state, $title, $department ) Set-Mailbox -Id

SQL Server创建存储过程(转载)

什么是存储过程? q       存储过程(procedure)类似于C语言中的函数 q       用来执行管理任务或应用复杂的业务规则 q       存储过程可以带参数,也可以返回结果 q       存储过程可以包含数据操纵语句.变量.逻辑 控制语句等 存储过程的优点 (1)执行速度快. 存储过程创建是就已经通过语法检查和性能优化,在执行时无需每次编译. 存储在数据库服务器,性能高. (2)允许模块化设计. 只需创建存储过程一次并将其存储在数据库中,以后即可在程序中调用该过程任意次.存储