PL/SQL 训练12--动态sql和绑定变量
--什么是动态SQL?动态PL/SQL
--动态SQL是指在运行时刻才构建执行的SQL语句
--动态PL/SQL是指整个PL/SQL代码块都是动态构建,然后再编译执行
--动态SQL来可以用来干什么?
--执行DDL语句
--支持WEB引用的即席查询和即席更新需求
--软编码的业务规则和公式
--先来看dbms_sql包的使用
DECLARE v_cur number;
v_sql varchar2(1000);
v_result number;
BEGIN
v_cur := dbms_sql.open_cursor;
v_sql := 'update ma_users set user_point = :point where user_name = :name';
dbms_sql.parse(v_cur, v_sql, dbms_sql.native);
dbms_sql.bind_variable(v_cur, ':point', 10000);
dbms_sql.bind_variable(v_cur, ':name', '乱世佳人');
v_result := dbms_sql.execute(v_cur);
dbms_sql.close_cursor(v_cur); END;
/
--NDS:原生动态SQL。相较于DBMS_SQL包执行动态SQL要简单的多
--怎么简单法呢?
--只要一个语句就够了
EXECUTE IMMEDIATE --立即执行
--语法
EXECUTE IMMEDIATE SQL_string
[into {defined_varibale[,defined_varibale2]...|record} ]
[using [in|out|in out]] bind_argument
[, [in|out|in out] bind_argument];
--sql_string :包含了SQL语句或者PL/SQL代码块的字符串表达式
--defined_varibale:用于接收查询中某一列值的变量
--record: 用户自定义类型或者基于%rowtype的记录,可以接收查询返回的一行值
--bind_argument:表达式,表达式的值将传给SQL语句或者PL/SQL块,也可以是一个标识符
--这个标识符作为PL/SQL块中调用的函数或者过程的输入或者输出变量
--into:这个字句用于单行的查询,对于查询结果的每一列的值,必须提供一个单独的变量或者一个兼容的记录类型的一个
--字段
--USING子句:利用这个子句给SQL字符串提供绑定参数,同时用于动态SQL和动态PL/SQL
--使用动态PL/SQL时可以指定一个参数模式,缺省模式是IN
DECLARE v_cur number;
v_sql varchar2(1000);
v_result number;
BEGIN v_sql := 'update ma_users set user_point = :point where user_name = :name';
execute immediate v_sql using 10000, '乱世佳人'; END;
/ --EXECUTE IMMEDIATE 可以用于除多行查询以外的SQL语句或者PL/SQL块 ,bulk collect INTO
--如果sql_string后面带分号,则会按照一个PL/SQL块来处理 否则就是DML或者DDL
--字符串可以带有绑定参数的占位符,但是对象的名字,比如表的名字或者列的名字,不能通过绑定变量传进去
DECLARE v_cur number;
v_sql varchar2(1000);
v_result number;
BEGIN v_sql := 'BEGIN update :TAB_NAME set user_point = :point where user_name = :name; END ;';
execute immediate v_sql
using 'MA_USERS',10000, '乱世佳人'; END;
/
--想一想为什么对象名字不能通过绑定变量进行传递?
--例子,
--最简单的例子,执行建表语句
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE USER_ORDER(USER_ID VARCHAR2(32),ORDER_ID VARCHAR2(32))';
END;
/
--更简单,可以创建通用的方法,比如
create or replace procedure exec_ddl(ddl_string in varchar2)
authid current_user
is
begin
EXECUTE IMMEDIATE ddl_string;
end ;
/
begin
exec_ddl('create table user_order_product(order_id varchar2(32),product_id varchar2(32))');
end ;
/ --传递表名,返回数量
create or replace function count_tab(i_table_name in varchar2)
return number is
v_count number;
begin EXECUTE IMMEDIATE 'select count(1) from ' || i_table_name
into v_count;
-- EXECUTE IMMEDIATE 'select count(1) from :table_name'
-- into v_count using i_table_name;
return v_count;
end;
/ begin
if count_tab('ma_users') <10 then
dbms_output.put_line('用户量不超过十个,太逊了');
end if;
end ;
/
--动态更新列,传进列的名称,就可以更新相应列的值
create or replace function update_col(i_col in varchar2,
i_val in varchar2,
i_start_date in date,
i_end_date in date) return number is begin
execute immediate 'update ma_users set ' || i_col ||
'=:1 where created_date between :2 and :3'
using i_val, i_start_date, i_end_date;
return sql%rowcount;
end;
/
--上述例子使用了绑定参数,对UPDAE语句分析结束后,引擎就会把几个占位符用USING子句中的值替换
--当一个语句在执行的时候,运行引擎会把SQL语句中的每一个占位符用USING语句中对应的绑定参数替换
--注意不能传进NULL直接量,必须通过一个数据类型正确但恰好是NULL值的变量传入
--using语句不能绑定专属于PL/SQL的数据类型,比如布尔类型,关联数组以及用户自定义的记录类型
--支持所有的SQL数据类型
--现在假设需要设计一个任务调度,可以每隔一段时间跑一次,需要入参可配置,任务也可配置 create table ma_schedue_task(task_id varchar2(50),procedure_name varchar2(100));
create table ma_schedue_param(task_id varchar2(50),param_order number,param_value varchar2(100));
declare
v_task_id varchar(32);
begin
insert into ma_schedue_task
values(sys_guid(), 'test_bind(:1,:2)')
returning task_id into v_task_id;
insert into ma_schedue_param values (v_task_id, 1, 'test1');
insert into ma_schedue_param values (v_task_id, 2, 'test2');
commit;
end;
/
create or replace procedure test_bind(i_test1 in varchar2,
i_test2 in varchar2) is begin
dbms_output.put_line(i_test1 || i_test2); end test_bind;
/
declare
cursor cur_task is
select * from ma_schedue_task;
v_sql varchar2(4000);
begin for v in cur_task loop
v_sql := ' begin execute immediate '' begin ' || v.procedure_name ||
' ; end;'' using ';
for param in (select r.param_value
from ma_schedue_param r
where r.task_id = v.task_id
order by param_order) loop
v_sql := v_sql || ' ''' || param.param_value || ''',';
end loop;
v_sql := rtrim(v_sql, ',') || '; end;'; dbms_output.put_line(v_sql);
execute immediate v_sql;
end loop;
end;
/
---OPEN FOR 语句
--上节课讲到游标变量时,用到这个语句
--这个语句可以用来实现多行的动态查询
--语法
OPEN {cursor_variable|:host_cursor_variable} for sql_string
[using bind_argument[,bind_argument]... ]; --cursor_variable; 弱类型的游标变量
-- :host_cursor_variable :在PL/SQL宿主环境比如OCI程序中声明的游标变量
-- sql_string: 包含了将要动态执行的SELECT 语句
--Using 字句:跟 execute immediate语句遵守同样的规则 create or replace function show_table(i_table in varchar2,
i_where in varchar2)
return sys_refcursor is
v_cur sys_refcursor;
begin open v_cur for 'select * from ' || i_table || ' where ' || i_where;
return v_cur;
end show_table;
/
declare
v_cur sys_refcursor;
v_user ma_users%rowtype;
begin
v_cur := show_table('ma_users', ' user_name=''乱世佳人''');
loop
fetch v_cur
into v_user;
exit when v_cur%notfound;
dbms_output.put_line(v_user.user_name || '积分' || v_user.user_point); end loop;
close v_cur;
end;
/
--一旦使用OPEN FOR 打开一个查询,接下来获取数据,关闭游标变量,检查游标属性的语法规则和静态游标变量
--以及硬编码的显示游标都是一样的
--执行一个OPEN FOR 语句是,PL/SQL引擎将会做以下事情
--用一个游标变量关联查询字符串中的查询语句
--对绑定参数值,然后用这些值替换查询字符串中的占位符
--执行查询
--识别出结果集
--将游标位置置于结果集的第一行
--把已处理行计数器归零,这个计数器也就是SQL/rowcount返回的值
--值得注意的是,查询语句中的任何绑定参数,都是游标变量在打开时才求值的
--也就是说,如果要把不同的绑定参数值用于同一个动态查询,必须用这些参数再执行一个新的OPEN FOR语句
create or replace procedure show_col(i_table in varchar2,
i_col in varchar2,
i_where in varchar2 := null) is
v_cur sys_refcursor;
v_val varchar2(1000);
begin
open v_cur for 'select ' || i_col || ' from ' || i_table || ' where ' || nvl(i_where,
' 1=1');
loop
fetch v_cur
into v_val;
exit when v_cur%notfound; if v_cur%rowcount = 1 then
dbms_output.put_line(i_col || ' of ' || i_table);
end if;
dbms_output.put_line(v_val);
end loop;
close v_cur;
end show_col;
/
begin
show_col('ma_users','user_name');
end ;
/
--上述例子把数据提取到一个单独的变量中,还可以把数据提取到一系列变量中
--也可以放到一个记录中
--可以为不同的需求创建不同类型的记录类型,这些类型可以放置包中,以便全局可用
--OPEN FOR 中的USING子句
--对于查询语句只能用IN 模式
--通过绑定参数,可以提升SQL语句性能,而且代码更容易编写和维护
--可以显著减少需要缓存在SGA中的编译后不同的语句数量
create or replace procedure show_col1(i_table in varchar2,
i_col in varchar2,
i_dcol in varchar2,
i_bg_date in date,
i_end_date in date) is
v_cur sys_refcursor;
v_val varchar2(1000);
begin
open v_cur for 'select ' || i_col || ' from ' || i_table || ' where ' || i_dcol || ' between :1 and :2'
using i_bg_date, i_end_date;
loop
fetch v_cur
into v_val;
exit when v_cur%notfound; if v_cur%rowcount = 1 then
dbms_output.put_line(i_col || ' of ' || i_table);
end if;
dbms_output.put_line(v_val);
end loop;
close v_cur;
end show_col1;
/ begin
show_col1('ma_users','user_name','REGISTER_DATE',date '2016-01-01',sysdate);
end ;
/
--四种动态SQL方法
-----------------------------------------------------------------------------------------------------------
--类型 说明 使用NDS语句
--第一种方法 非查询;只用于UPATE,INSERT,MERGE,DELETE和DDL语句且不带有绑定变量 不带USING into子句的
-- EXECUTE IMMEDIATE语句
--第二种方法 非查询;只用于UPATE,INSERT,MERGE,DELETE且带有绑定变量个数固定 带有USING子句的
-- EXECUTE IMMEDIATE语句
--第三种方法 带有确定数量的列和绑定变量,返回只有一行数据 带有USING into子句的
--之单行查询 EXECUTE IMMEDIATE语句
--第三种方法之 带有固定数量的列和绑定变量,返回多行数据 带有USING BULK COLLECT INTO 的EXECUTE IMMEDIATE语句
--多行查询 或者动态字符串的OPEN FOR 语句
--第四种方法 语句中选定的列的数量或者绑定数量等到允许时刻才能确定 使用DBMS_SQL包
--
-------------------------------------------------------------------------------------------------------------
--绑定变量
--使用绑定变量的规则和情况
--SQL语句中可以绑定的是,可以把动态字符串中的占位符替换成数值的直接量(文本,变量,复杂的表达式)
--不能绑定模式元素的名字(表或者列)或者SQL语句的一整块,比如where 子句
--对于这部分,必须使用拼接的方式
begin
execute immediate 'update :table set :col = :value where 1=1'
using 'ma_users', 'user_point', 10000;
end;
/
--为什么会有一个限制呢?
--当给EXECUTE IMMEDIATE 传入一个字符串时,运行时引擎首先必须要解析这个语句
--解析的目的是保证SQL语句是定义良好的
begin
execute immediate 'update ma_users set user_point = :value where 1=1'
using 10000;
end;
/
--参数的模式:in,out,in out
--执行动态查询时,所有的绑定参数都必须是IN 模式,除非使用了RETURNING
DECLARE
V_POINT NUMBER := 1000;
V_NAME VARCHAR2(20) := '乱世佳人';
V_PHONE varchar2(50);
begin
execute immediate 'update ma_users set user_point = :value where USER_NAME= :NAME
RETURNING USER_PHONE INTO :PHONE'
using V_POINT, V_NAME, OUT V_PHONE;
dbms_output.put_line(v_phone);
end;
/
--除了能用在RETURNING子句,OUT,IN OUT模式的绑定参数在执行动态PL/SQL时发挥比较大的作用
--在动态PL/SQL中绑定参数的模式必须要和PL/SQL程序中参数模式一致 --重复的占位符
--NDS根据位置而不是名字把USING语句的绑定参数关联到占位符的
--当执行一个动态SQL字符串,必须为每一个占位符提供一个参数,即便这些占位符是重复的
--如果执行的是一个动态PL/SQL块,必须为每一个唯一占位符提供一个参数
DECLARE
V_POINT NUMBER := 1000;
V_NAME VARCHAR2(20) := '乱世佳人';
V_PHONE varchar2(50);
V_email varchar2(50);
begin
execute immediate 'update ma_users set user_point = :value where USER_NAME= :value
RETURNING USER_PHONE,user_email INTO :1,:2'
using V_POINT, V_NAME, OUT V_PHONE, out V_email;
dbms_output.put_line(v_phone || V_email);
end;
/ DECLARE
V_POINT NUMBER := 1000;
V_NAME VARCHAR2(20) := '乱世佳人';
V_PHONE varchar2(50);
V_email varchar2(50);
begin
execute immediate 'begin update ma_users set user_name = :value where USER_NAME= :value
RETURNING USER_PHONE,user_email INTO :1,:2 ; end ;'
using V_NAME, OUT V_PHONE,out V_email;
dbms_output.put_line(v_phone||v_email);
end;
/
--NULL值的传递
--把NULL值隐藏在一个变量后面
--通过转换函数把NULL值显示的转换为一个有类型的值 DECLARE
V_POINT NUMBER := null;
V_NAME VARCHAR2(20) := '乱世佳人';
V_PHONE varchar2(50);
begin /*execute immediate 'update ma_users set user_point = :value where USER_NAME= :NAME
RETURNING USER_PHONE INTO :PHONE'
using null, V_NAME, OUT V_PHONE;
dbms_output.put_line(v_phone);*/ /*execute immediate 'update ma_users set user_point = :value where USER_NAME= :NAME
RETURNING USER_PHONE INTO :PHONE'
using V_POINT, V_NAME, OUT V_PHONE;
dbms_output.put_line(v_phone);
*/ execute immediate 'update ma_users set user_point = :value where USER_NAME= :NAME
RETURNING USER_PHONE INTO :PHONE'
using to_number(null), V_NAME, OUT V_PHONE;
dbms_output.put_line(v_phone);
end;
/
---动态PL/SQL
--NDS可以为我们做以下事情
--创建一个程序,包括带有全局访问的数据结构的包
--通过名字获得或修改全局变量的值
--调用那些在编译时刻还不知道名字的函数或者过程
--使用动态PL/SQL块和NDS的规则和技巧
--动态字符串必须是一个有效的PL/SQL块,这个块必须以DECLARE或者BEGIN关键字开始
--使用END关键字和分号结束。如果字符串不以分号结尾,是不会被识别成PL/SQL块的
--在动态块中,只能访问属于全局范围的PL/SQL代码元素。动态块是在局部包围块的作用范围之外执行的
--在动态PL/SQL块中抛出的错误可以在运行EXECUTE IMMEDIATE语句的局部块中捕获并处理
create or replace procedure do_plsql(i_plsql in varchar2)
is
begin
execute immediate 'begin '|| rtrim(i_plsql,';')||' ; end ;';
end ;
/
--下面这个例子反映了规则二
declare
num number ;
begin
do_plsql('num := 5');
exception
when others then
dbms_output.put_line(sqlerrm);
end ;
/ begin
<<test>>
declare
num number;
begin
do_plsql('test.num := 5');
end;
end;
/
create or replace package pkgvars
is
num number ;
end pkgvars; declare
num number ;
begin
do_plsql('pkgvars.num := 5;');
end ;
/
--用动态块替换重复的代码
--比如有以下方法
procedure do_task(task_name in varchar2) is begin
if task_name = 'test' then
test;
elsif task_name = 'test2' then
test2;
......
end if;
end ;
/
procedure do_task(task_name in varchar2) is begin
execute immediate
'begin '||task_name||' ; end ;';
end ;
/
--NDS的建议
--对于共享的程序使用调用者权限
create or replace procedure exec_ddl(ddl_string in varchar2)
authid current_user
is
begin
EXECUTE IMMEDIATE ddl_string;
end ;
/ --预估并处理动态的错误
--如果使用大量的动态SQL,很容易迷失方向以至于在代码调试上浪费大量时间
--在调用EXECUTE IMMEDIATE和OPEN FOR 时,总是带上一个异常处理单元
--在每一个异常处理句柄,记录下显示错误发生时的错误信息以及SQL语句
--可以考虑在这些语句之前加上一个“跟踪机制”
create or replace procedure exec_ddl(ddl_string in varchar2)
authid current_user
is
begin
EXECUTE IMMEDIATE ddl_string;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.put_line('FAILLURE:'||DBMS_UTILITY.format_error_backtrace);
DBMS_OUTPUT.put_line('ON :'||ddl_string);
end ;
/ --使用绑定而不是拼接
DECLARE
V_POINT NUMBER := 1000;
V_NAME VARCHAR2(20) := '乱世佳人';
V_PHONE varchar2(50);
begin
execute immediate 'update ma_users set user_point = :value where USER_NAME= :NAME'
using V_POINT, V_NAME
dbms_output.put_line(v_phone);
end;
/
DECLARE
V_POINT NUMBER := 1000;
V_NAME VARCHAR2(20) := '乱世佳人';
V_PHONE varchar2(50);
begin
execute immediate 'update ma_users set user_point =' || V_POINT ||
'where USER_NAME=''' || V_NAME || '''';
dbms_output.put_line(SQL%ROWCOUNT);
end;
/
--只要有可能使用绑定的方式就不要依赖与拼接
--绑定通常更快速
--绑定的编写和维护都很容易
--绑定有助于避免隐式转换
--绑定避免了发生代码注入的可能性
--对于一些场景,如果使用拼接更有效,那也要毫不犹豫的使用拼接方式
--把代码注入的风险最小化
create or replace procedure show_table1(i_table in varchar2,
i_where in varchar2) is
v_sql varchar2(1000);
begin
v_sql := 'declare v_row ' || i_table || '%rowtype;
begin
select * into v_row from ' || i_table || ' where ' || i_where || '
end ;';
dbms_output.put_line(v_sql);
-- execute immediate v_sql;
end show_table1;
/ declare
begin
show_table1('ma_users',
' user_name=''乱世佳人'';delete from ma_users ; ');
end;
/ --代码注入也叫SQL注入,可以严重的威胁程序的安全,动态PL/SQL块的执行为代码注入开启了最大的可能性
--限制用户权限
--尽可能使用绑定变量,但使用绑定,也丧失了一些灵活性
--检测动态文本中的危险文本
--用DBMS_ASSERT检验输入
DBMS_ASSERT.SIMPLE_SQL_NAME ---什么时候使用DBMS_SQL
---解析非常长的字符串
--EXECUTE IMMEDIATE 执行的字符串大小限制32K,在11g中可以处理一个CLOB,最大长度4GB
dbms_sql.parse --可以解析任意长度的SQL和PLSQL ---得到查询的列的信息
--dbms_sql可以对动态游标中的列进行描述,以记录的关联数组的形式返回每个列的信息
--用这个功能,可以写出非常通用的游标处理代码
--动态SQL的第四种方法
declare
cur pls_integer := dbms_sql.open_cursor;
cols dbms_sql.desc_tab;
ncols pls_integer;
begin
dbms_sql.parse(cur,'select user_name ,user_point from ma_users',dbms_sql.native);
dbms_sql.describe_columns(cur,ncols,cols);
for i in 1..ncols loop
dbms_output.put_line(cols(i).col_name);
end loop ;
dbms_sql.close_cursor(cur);
end ;
/
--实现第四种方法的动态SQL的需求
declare
cursor cur_task is
select * from ma_schedue_task;
v_sql varchar2(4000);
v_cur number;
v_result number;
begin for v in cur_task loop
v_sql := ' begin ' || v.procedure_name || ';end;';
v_cur := dbms_sql.open_cursor;
dbms_sql.parse(v_cur, v_sql, dbms_sql.native);
for param in (select r.param_order, r.param_value
from ma_schedue_param r
where r.task_id = v.task_id
order by param_order) loop
dbms_sql.bind_variable(v_cur,
':' || param.param_order,
param.param_value);
end loop;
v_result := dbms_sql.execute(v_cur);
dbms_sql.close_cursor(v_cur);
end loop;
end;
/
--11g新特性
dbms_sql.to_refcursor --原生态动态sql和DBMS_SQL的交互 declare
type string_t is table of varchar2(100); function get_data(i_where in varchar2, i_value in string_t)
return sys_refcursor is
v_sql varchar2(1000);
v_cur number;
v_result number;
v_result_cur sys_refcursor;
begin
v_sql := 'select * from ma_users where ' || i_where;
v_cur := dbms_sql.open_cursor;
dbms_sql.parse(v_cur, v_sql, dbms_sql.native);
for i in 1 .. i_value.count loop
dbms_sql.bind_variable(v_cur, ':' || i, i_value(i));
end loop;
v_result := dbms_sql.execute(v_cur);
v_result_cur := dbms_sql.to_refcursor(v_cur);
return v_result_cur;
end get_data;
begin
declare
v_cur sys_refcursor;
v_row ma_users%rowtype;
begin
v_cur := get_data(' user_name=:1', string_t('乱世佳人'));
loop
fetch v_cur
into v_row;
exit when v_cur%notfound;
dbms_output.put_line(v_row.user_point);
end loop;
close v_cur;
end;
end;
/
PL/SQL 训练12--动态sql和绑定变量的更多相关文章
- PL/SQL开发中动态SQL的使用方法
一般的PL/SQL程序设计中,在DML和事务控制的语句中可以直接使用SQL,但是DDL语句及系统控制语句却不能在PL/SQL中直接使用,要想实现在PL/SQL中使用DDL语句及系统控制语句,可以通过使 ...
- .Net程序员学用Oracle系列(28):PLSQL 之SQL分类和动态SQL
1.SQL 语句分类 1.1.分类方法及类型 1.2.数据定义语言 1.3.数据操纵语言 1.4.其它语句 2.动态 SQL 理论 2.1.动态 SQL 的用途 2.2.动态 SQL 的语法 2.3. ...
- MyBatis框架之SQL映射和动态SQL
使用MyBatis实现条件查询 1.SQL映射文件: MyBatis真正的强大之处就在于SQL映射语句,MyBatis专注于SQL,对于开发人员来说也是极大限度的进行SQL调优,以保证性能.下面是SQ ...
- Error querying database. Cause: java.sql.SQLException: ORA-01745: 无效的主机/绑定变量名
今天调试程序是遇到了,下面的一个问题.我将对应的SQL语句拿到Toad下也能正常的执行,感觉有点莫名其妙,根据异常信息的提示查看对应的映射结果集也没发现错误,然后百度了一下,也有许多朋友也遇到过这样的 ...
- 数据库系统学习(十)-嵌入式SQL语言之动态SQL
第十讲 嵌入式SQL语言之动态SQL 静态SQL 区别变量和属性:高级语言向嵌入式SQL传递变量的方法 动态SQL 动态构造SQL语句是应用程序员必须掌握的重要手段 SQL语句的动态构造示例 根据界面 ...
- 小峰mybatis(5)mybatis使用注解配置sql映射器--动态sql
一.使用注解配置映射器 动态sql: 用的并不是很多,了解下: Student.java 实体bean: package com.cy.model; public class Student{ pri ...
- SQL SERVER 执行动态SQL EXEC
:普通SQL语句可以用Exec执行 eg: Select * from tableName Exec('select * from tableName') Exec sp_executesql N's ...
- SQL Server 2012 - 动态SQL查询
动态SQL的两种执行方式:EXEC @sql 和 EXEC sys.sp_executesql @sql DECLARE @c_ids VARCHAR(200) SET @c_ids ='1,2' - ...
- (四)resultMap、sql片段与动态SQL
一.resultMap 1.1 为什么要用resultMap resultType:指定输出结果的类型(pojo.简单类型.hashmap),将SQL查询结果映射为Java对象. 使用resultTy ...
随机推荐
- spark UDAF
感谢我的同事 李震给我讲解UDAF 网上找到的大部分都只有代码,但是缺少讲解,官网的的API有讲解,但是看不太明白.我还是自己记录一下吧,或许对其他人有帮助. 接下来以一个求几何平均数的例子来说明如何 ...
- GO学习笔记:函数defer
Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句.当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回.特别是当你在进行一些打开资源的操作时,遇 ...
- TimeSpan 结构(struct)
TimeSpan 是结构类型(struct),即值类型,可以通过两个DateTime(struct)之差来获得,如下例子: DateTime departure = new DateTime(2010 ...
- poj3517约瑟夫问题
直接套公式+ 假设除去第k个人. 0, 1, 2, 3, ..., k-2, k-1, k, ..., n-1 //original sequence (1) 0, 1, 2, 3, ..., k-2 ...
- 51nod 1639 递推
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1639 1639 绑鞋带 基准时间限制:1 秒 空间限制:131072 K ...
- Flask 分页的简单用法 / flask_sqlalchemy /无刷新翻转页面(原创)
flask_sqlalchemy对象提供分页方法 1. 后台views代码: from models import <table_name> #导入model的对象 @app.route( ...
- C++轮子队-第五周--测试与发布
Alpha版本测试报告 测试找出的BUG 测试结果bug清单: 修复的bug: 按方向下键部分情况无法合并的bug 棋盘图形布局错乱的bug 分数显示不出来的bug 重开游戏无法下坠方块的bug 无法 ...
- Java.lang包的接口解读
Java.lang包中提供了八个接口: 1.Appendable 能够被追加 char 序列和值的对象.如果某个类的实例打算接收来自 Formatter的格式化输出,那么该类必须实现 Appendab ...
- [置顶]
Android App引导页这些坑你自己犯过吗?
场景:测试机:华为荣耀6x 今天我自己掉入一个很蠢蠢的坑,一个引导页搞了20多分钟,不管我怎么测试用真机还是模拟器都无法运行,但是我写的demo完全没问题,好无语,我都怀疑我是不是搞android,我 ...
- Go开发Struct转换成map两种方式比较
最近做Go开发的时候接触到了一个新的orm第三方框架gorose,在使用的过程中,发现没有类似beego进行直接对struct结构进行操作的方法,有部分API是通过map进行数据库相关操作,那么就需要 ...