首页 | 摘要显示 | 上一页 1 2 3 4 5 6 7 8 9 10 11 下一页

Developer Archives

March 21, 2007

在Perl中如何派生多进程 -- fork函数

    这个函数当前在学校没有搞懂, 刚从学校出来时也没搞懂, 不会用他来写多线程程序. 今天有人问我在Perl中如何进行多进程编程, 去Google了一把, 发现境界好象比以前高了, 因为感觉上懂了一些了. 下面是写的一个例子:

#!/usr/bin/perl
#

my $pid = fork();

if (!defined($pid))
{
   print ("Fork process failured!\n");
   exit();
}

if ($pid)
{
     # This is the child process.
     sleep(1);
     print ("exit child after 10 seconds wait!\n");
     exit();
}
else
{
     # This is the parent process.
     print ("exit parent!\n");
}

    毕业后的这么多年中, 只有用Java来写过多线程序, 不过它可没有fork函数, 但感觉上, 他们也没有什么区别. 看来可以为refresh_mysql.pl角本增加并行执行支持了. cool!

March 23, 2007

让Perl DBI返回的记录按列存贮

    最新版本的Perl DBI接口定义了Array DML接口, 指将一个数组作为一个绑定变量, 这个在数据库的接口层上是早已经支持的了, 象Oracle Pro*C中早就支持命名用数组了. 但在实际使用中, 去发现一点不方便的地方. 通常Perl中返回结果集是按行排列的, 如下所示:

{
  ROW1  {col1, col2, col3, col4},
  ROW2  {col1, col2, col3, col4},
  .....
  ROWn  {col1, col2, col3, col4}
}

    但实际上在绑定时, 是这样的:

$sth->bind_param_array( COL1={row1, row2, ... rown});
$sth->bind_param_array( COL2={row1, row2, ... rown});
.....
$sth->bind_param_array( COLn={row1, row2, ... rown});

    因此需要转换, 但其实数据库底层(象OCI)使用Array Fetch时传回来的方式是按列存贮的, 如下所示:

COL1={ROW1, ROW2, ..., ROWn}
COL2={ROW1, ROW2, ..., ROWn}
......
COLn={ROW1, ROW2, ..., ROWn}

    在很多时侯, Perl在取回时进行了从列到行的转换, 我们在绑定时又进行了从行到列的转换, 有点多此一举啊, 影响效率.

March 24, 2007

在MySQL中建立实体化视图日志

    在MySQL中建立实体化视图日志表, 在这里基表表名是T_MVLOG, 主键字段是COL1. 日志表结构如下:

CREATE TABLE MLOG$_T_MVLOG
(
   SEQUENCE$$ BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
   DMLTYPE$$ CHAR,
   COL1 BIGINT
);

    Oracle中的实体化视图是用触发器来实现的, 不同的是早期版本是用Internal Trigger(但还可以在Trigger$表中查到), 而在8i及以后的版本中, 则变为Kernel Level Trigger(在Trigger$中是找不到了). 我们现在在MySQL中手工建立触发器, 说不定以后MySQL真的也引入实体化视图功能呢? 也在Kernel级别来实现呢? 发现建立触发器的语句好象Oracle的PL/SQL.

DELIMITER |

CREATE TRIGGER TLOG$_I_T_MVLOG BEFORE INSERT ON T_MVLOG
  FOR EACH ROW BEGIN
    INSERT INTO MLOG$_T_MVLOG (DMLTYPE$$,COL1) VALUES ('I',NEW.COL1);
  END;
|

CREATE TRIGGER TLOG$_U_T_MVLOG BEFORE UPDATE ON T_MVLOG
  FOR EACH ROW BEGIN
    IF (NEW.COL1 = OLD.COL1) THEN
      INSERT INTO MLOG$_T_MVLOG (DMLTYPE$$,COL1) VALUES ('U',OLD.COL1);
    ELSE
      INSERT INTO MLOG$_T_MVLOG (DMLTYPE$$,COL1) VALUES ('D',OLD.COL1);
      INSERT INTO MLOG$_T_MVLOG (DMLTYPE$$,COL1) VALUES ('I',NEW.COL1);
    END IF;
  END;
|

CREATE TRIGGER TLOG$_D_T_MVLOG BEFORE DELETE ON T_MVLOG
  FOR EACH ROW BEGIN
      INSERT INTO MLOG$_T_MVLOG (DMLTYPE$$,COL1) VALUES ('D',OLD.COL1);
  END;
|

DELIMITER ;

    看看触发器是否工作正常吧:

mysql> INSERT INTO T_MVLOG VALUES (1000,'LOU',100.10,'FANGXIN');
Query OK, 1 row affected (0.07 sec)

mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM MLOG$_T_MVLOG;
+------------+-----------+------+
| SEQUENCE$$ | DMLTYPE$$ | COL1 |
+------------+-----------+------+
|          1 | I         | 1000 |
+------------+-----------+------+
1 row in set (0.00 sec)

    运行refresh_mysql.pl, 将数据从MySQL中复制到Oracle中, 分别在MySQL和Oracle查询日志表和目标表:

mysql> select * from mlog$_t_mvlog;
Empty set (0.00 sec)

SQL> select * from t_mvlog;

COL1 COL2       COL3 COL4
---- ---- ---------- ----------
1000 LOU       100.1 FANGXIN

    继续检查这些触发器, 在Update时能不能正常工作:

mysql> update t_mvlog set col1='1001';
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from mlog$_t_mvlog;
+------------+-----------+------+
| SEQUENCE$$ | DMLTYPE$$ | COL1 |
+------------+-----------+------+
|          2 | D         | 1000 |
|          3 | I         | 1001 |
+------------+-----------+------+
2 rows in set (0.00 sec)

    DELETE的结果就不写在这儿了, 要不太长了.

April 10, 2007

Perl的如何操作文件 -- FileHandle

    这几天连续写了几个Perl程序, 有的是自愿写的, 有的是任务型的, 这都无所谓了. 在所有的程序中都有一个共同点, 那就是要么程序要输出到屏蔽, 要么输出到一个文件, 对于刚学Perl的我来说, 这个地方也是花了不少时间查有关资料的, 不过最后让我明白的文档是Perl Doc站点上的FileHandle说明文档. 先说说我是如何处理的.

    在我的程序中, 如果在命令行指定了一个log文件名的话, 就向log文件写, 否则就向屏蔽写出. 大致代码如下:

use FileHandle;
......
sub openFile
{
   my ($logfile) = @_;
   my ($fh);

   if (defined($logfile))
   {
      $fh = new FileHandle($logfile, "w+");
   }
   else
   {
      $fh = new FileHandle();
      $fh = fdopen(fileno(STDOUT), "w+");
   }
   $fh;
}

    接下来就可以调用了, 如果返回一个未定义(undef)的值, 则表示不能写出到日志文件了. 否则可以调用如下方法, 向文件输出了:

$logfile->print(...);
$logfile->printf(...);

    我还改了写文件操作的一个属性, 就是无论写什么, 写多少东西都进行flush操作, 这样的话可以用"tail -f"来看程序进行到那一步了, 代码如下:

$logfile->autoflush(1);

    关于更多的调用方法, 可以参考IO::Handle包的说明.

April 26, 2007

WE8ISO8859P1字符集下,JDBC的中文支持问题

    当数据库的字符集为US7ASCII, WE8DEC, WE8ISO8859P1及WE8MSWIN1252等单字节的字符集时, 使用JDBC时总发现不能准确地处理中文字符, 这个问题几年前就困扰着我, 一直也没有解决的办法. 以前遇到这些数据库的字符集时, 总是将$JAVA_HOME\lib目录下的charsets.jar移走来解决, 但是这样并不能解决CLOB中的中文字符问题. 昨天coolyl又问了这个同样的问题, 我在试验时发现JRE 1.6版本和JRE 1.4版本有所区别, 通过用-Dfile.encoding=ISO-8859-1的命令行选项, 在1.6下可以成功显示汉字, 而1.4下面同样的方法却不行.

c:\jdk\sun160\bin\java -Dfile.encoding=ISO-8859-1 -jar jlib\oasql.jar
c:\jdk\sun142\bin\java -Dfile.encoding=ISO-8859-1 -jar jlib\oasql.jar

    使用1.6版本的JRE时, 情况如下:

ASQL> select * from nls_database_parameters
    2    where parameter='NLS_CHARACTERSET';

PARAMETER        VALUE
---------------- ------------
NLS_CHARACTERSET WE8ISO8859P1

1 rows returned.

ASQL> SELECT '中国' as COL1 FROM DUAL;

COL1
----
中国

1 rows returned.

    而使用1.4版本的JRE时, 情况如下:

ASQL> SELECT '中国' as COL1 FROM DUAL;

COL1
----
-?

1 rows returned.

    以上测试在Windows的Command窗口中测试, 机器的Locale为中国, 不知道其他的同行或Java的开发人员有什么好的建议?

上一页 1 2 3 4 5 6 7 8 9 10 11 下一页

当前分类: Developer

Creative Commons License
本站版权: 共用创作 CC
署名-非商业性-相同方式分享
本站基于MT-3.36免费版
(©)版权所有, 2004 - 2008, www.AnySQL.net, 保留所有权利.
MSN: loufangxin(a)msn.com, Mail: anysql(at)126.com/support(at)iamdba.com, Skype ID:anysql