PHP学会网 php培训网 PHP暑期培训 PHP寒假培训 PHP假期培训 » PHP中高级 » 新来报到,顺便谈谈为什么总是盯着MySQL进行应用,不想考虑一下PostgreSQL吗?
本页主题: 新来报到,顺便谈谈为什么总是盯着MySQL进行应用,不想考虑一下PostgreSQL吗? 打印 | 加为IE收藏 | 收藏主题 | 上一主题 | 下一主题

自由的龙

该用户目前不在线
级别: 中级程序员
精华: 1
发帖: 1264
威望: 1267 点
金钱: 12660 PYMB
贡献值: 0 点
在线时间:0(小时)
注册时间:2006-04-16
最后登录:2006-06-27

新来报到,顺便谈谈为什么总是盯着MySQL进行应用,不想考虑一下PostgreSQL吗?


PostgreSQL(简称PgSQL)是一种支持SQL99标准的开源关系型数据库,而MySQL仅支持SQL92标准,曾经看过一篇文章,标题大概是:“MySQL除了Insert、update、delecte、Select还能给我们提供什么?”。而PgSQL还支持触发器、存储过程、规则函数等等,这样我们的在程序开发中的很多数据逻辑(数据结构)都可以放在数据库中,而不需要用PHP来完成。

现在PgSQL支持在Win、Linux、FreeBSD、MacOS等大多数操作系统上安装使用,如果像MySQL那样不使用他的存储过程、触发器这些特性,和MySQL是一样的用法。网上也有人说PgSQL的速度比MySQL慢,我觉得这是不公平的比较,就像一辆0.8L的QQ在高速路上跑的速度跟一辆奥迪A4 1.8T在城市里跑的速度来进行比较一样根本不具备可比性,就像下面这样的递归应用,用PHP+MySQL来完成所花的时间,跟PHP+PgSQL来比较,数据量增加,MySQL所花的时间将成几何积数增长,而PgSQL始终变化就在一个范围内。

    比如一个无限分类的递归应用,用PHP来写,可能要一大篇,数据反复在数据库和程序之间交换,现在我们用PgSQL来实现,看看效果又是如何:


CODE:[Copy to clipboard]数据表modules
CREATE TABLE "public"."modules" (
"id" SERIAL,
"bom_id" INTEGER DEFAULT 0 NOT NULL,
"group_id" INTEGER NOT NULL,
"names" VARCHAR(20) NOT NULL,
"link" VARCHAR(50),
"taxis" INTEGER DEFAULT 0,
CONSTRAINT "modules_pkey" PRIMARY KEY("id"),
FOREIGN KEY ("group_id")
  REFERENCES "public"."groups"("id")
  ON DELETE NO ACTION
  ON UPDATE NO ACTION
  NOT DEFERRABLE
) WITHOUT OIDS;



CODE:[Copy to clipboard]数据视图modules_view
CREATE OR REPLACE VIEW "public"."modules_view" (
  id,
  bom_id,
  taxis,
  names,
  link,
  group_id,
  group_name,
  group_link)
AS
SELECT m.id, m.bom_id, m.taxis, m."names", m.link, g.id AS group_id, g."names"
  AS group_name, g.link AS group_link
FROM modules m, groups g
WHERE (m.group_id = g.id);



CODE:[Copy to clipboard]通过id值查询父阶的过程函数
CREATE OR REPLACE FUNCTION "public"."bom_parent" (parent_table varchar, parent_id integer) RETURNS SETOF "public"."bom_ex" AS
$body$
/* 通过id值查询父阶 */
DECLARE
    ENDTREE INTEGER;
    NLVL INTEGER;
    REC INTEGER;
    RESULT "public"."bom_ex"%ROWTYPE;
    QUERY VARCHAR;

BEGIN
  ENDTREE:=0;
  NLVL:=1;

  IF ps_temp_table('STACK') THEN
    RAISE NOTICE 'TEMP TABLE "STACK" EXISTS!';
  ELSE
      CREATE TEMP TABLE STACK(
        id INTEGER,
        compositor INTEGER,
        sub_menu BOOLEAN,
        end_menu BOOLEAN
      ) WITHOUT OIDS ON COMMIT DELETE ROWS;
  END IF;

  IF ps_temp_table('STACK_TEMP') THEN
    RAISE NOTICE 'TEMP TABLE "STACK_TEMP" EXISTS!';
  ELSE
      CREATE TEMP TABLE STACK_TEMP(
        partno INTEGER,
        parent INTEGER,
        LVLS INTEGER,
        sub_menu BOOLEAN,
        end_menu BOOLEAN
      ) WITHOUT OIDS ON COMMIT DELETE ROWS;
  END IF;

  EXECUTE 'INSERT INTO STACK_TEMP(partno, parent, LVLS, sub_menu, end_menu)
        SELECT id, bom_id, 1, TRUE, TRUE FROM '||parent_table||'
        WHERE id='||parent_id;

  WHILE (ENDTREE=0) LOOP
      NLVL := NLVL + 1;

      EXECUTE 'INSERT INTO STACK_TEMP(partno, parent, LVLS, sub_menu, end_menu)
            SELECT A.id, A.bom_id, '||NLVL||',TRUE, TRUE
            FROM '||parent_table||' A, STACK_TEMP B
            WHERE A.id = B.parent AND A.id <> 0
            AND B.LVLS = '||NLVL||' -1';

      IF NOT EXISTS(SELECT partno FROM STACK_TEMP WHERE LVLS = NLVL) THEN
        UPDATE STACK_TEMP SET sub_menu = FALSE WHERE LVLS = NLVL - 1;
        ENDTREE := 1;
      END IF;
  END LOOP;

  INSERT INTO STACK(id, compositor, sub_menu, end_menu)
  SELECT partno, LVLS, sub_menu, end_menu
  FROM STACK_TEMP;

  QUERY := 'SELECT s.id AS id, s.compositor AS compositor, t.bom_id AS bom_id,
              t.taxis AS taxis, t.names AS names, t.link AS link,
              t.group_id AS group_id, t.group_name AS group_name,
              t.group_link AS group_link, s.sub_menu AS sub_menu,
              s.end_menu AS end_menu
            FROM STACK s, '||parent_table||' t
            WHERE s.id=t.id';
  FOR RESULT IN EXECUTE QUERY LOOP
    RETURN NEXT RESULT;
  END LOOP;
  RETURN;
END
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;



CODE:[Copy to clipboard]通过id值查询子阶的过程函数
CREATE OR REPLACE FUNCTION "public"."bom_part" (part_table varchar, part_id integer) RETURNS SETOF "public"."bom_ex" AS
$body$
/* 通过id值查询子阶 */
DECLARE
    LVL INTEGER;
    ROWCOUNT INTEGER;
    RESULT public.bom_ex%ROWTYPE;
    PARTMODE INTEGER;
    QUERY VARCHAR;
BEGIN
  LVL:=1;
  PARTMODE:=part_id;
  IF ps_temp_table('STACK') THEN
    RAISE NOTICE 'TEMP TABLE "STACK" EXISTS!';
  ELSE
      CREATE TEMP TABLE STACK(
        id INTEGER,
        compositor INTEGER,
        sub_menu BOOLEAN DEFAULT FALSE,
        end_menu BOOLEAN DEFAULT FALSE
      ) WITHOUT OIDS ON COMMIT DELETE ROWS;
  END IF;

  IF ps_temp_table('STACK_TEMP') THEN
    RAISE NOTICE 'TEMP TABLE "STACK_TEMP" EXISTS!';
  ELSE
      CREATE TEMP TABLE STACK_TEMP(
        partno INTEGER,
        LVLS INTEGER,
        taxis INTEGER
      ) WITHOUT OIDS ON COMMIT DELETE ROWS;
  END IF;

  EXECUTE 'INSERT INTO STACK_TEMP(partno, LVLS, taxis)
        SELECT id,1,taxis FROM '||part_table||'
        WHERE id = '||PARTMODE;

  WHILE (LVL>0) LOOP
      IF EXISTS(SELECT partno FROM STACK_TEMP WHERE LVLS=LVL) THEN

        SELECT partno INTO PARTMODE
        FROM STACK_TEMP
        WHERE LVLS=LVL
        ORDER BY taxis;

        INSERT INTO STACK(id,compositor)
        SELECT partno,LVL
        FROM STACK_TEMP
        WHERE LVLS=LVL
        AND partno=PARTMODE;

        DELETE FROM STACK_TEMP
        WHERE LVLS=LVL
        AND partno=PARTMODE;

        EXECUTE 'INSERT INTO STACK_TEMP(partno,LVLS,taxis)
              SELECT id,'||LVL+1||',taxis FROM '||part_table||'
              WHERE bom_id='||PARTMODE;

        GET DIAGNOSTICS ROWCOUNT = ROW_COUNT ;
        IF ROWCOUNT > 0 THEN
          UPDATE STACK SET sub_menu = true WHERE id=PARTMODE;
          LVL := LVL + 1;
        END IF;
      ELSE
          UPDATE STACK SET end_menu = true WHERE id=PARTMODE;
          LVL := LVL - 1;
      END IF;
  END LOOP;

  QUERY := 'SELECT s.id AS id, s.compositor AS compositor, t.bom_id AS bom_id,
              t.taxis AS taxis, t.names AS names, t.link AS link,
              t.group_id AS group_id, t.group_name AS group_name,
              t.group_link AS group_link, s.sub_menu AS sub_menu,
              s.end_menu AS end_menu
          FROM STACK s, '||part_table||' t
          WHERE s.id=t.id';
  FOR RESULT IN EXECUTE QUERY LOOP
      RETURN NEXT RESULT;
  END LOOP;
  RETURN;
END
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;



CODE:[Copy to clipboard]数据
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (0, -1, 0, '', NULL, 0);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (1, 0, 1, '系统设定', '', 8);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (2, 0, 1, '系统用户', '', 9);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (3, 2, 4, '系统用户管理', 'Users', 1);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (4, 1, 1, '后台模块管理', 'ModuleManage', 1);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (5, 2, 1, '系统用户组管理', 'Groups', 2);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (6, 2, 0, '退出注销', 'Logout', 4);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (7, 2, 5, '修改密码', 'UserPassword', 3);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (8, 1, 6, '版权信息管理', 'CopyRight', 2);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (10, 0, 0, '新闻文章', '', 1);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (11, 10, 5, '专辑文章管理', '', 3);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (12, 10, 4, '文章分类管理', 'ArticleClass', 1);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (13, 10, 5, '新闻文章管理', 'Article', 2);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (14, 0, 5, '软件下载', '', 2);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (15, 1, 4, '前台设定管理', 'WebsiteConf', 3);
INSERT INTO modules (id, bom_id, group_id, "names", link, taxis) VALUES (16, 2, 1, '网络站点管理', 'WebSite', 1);
在php、jsp、 asp 或者java这些程序中我们只用简单第发出一个命令,我们就可以或者一组递归显示的数据:


CODE:[Copy to clipboard]SELECT * FROM bom_part('modules_view', 0)
这样是不是很简单呢?
顶端 Posted: 2006-04-25 11:56 | [楼 主]
PHP学会网 php培训网 PHP暑期培训 PHP寒假培训 PHP假期培训 » PHP中高级

时:11-23 19:56 Copyright © 2006 phpwhy.com 权
ICP05060669

曳息 -