Posted by bianbian on 2008-04-02 09:16
本文Tags: SQL, 数据库
SQL语句的需求真是无止境,今天又有一个:需要保留数据表内最后N条记录。
这个需求还是经常碰到的:
比如实时更新的滚动新闻,只需要保留最后的N条,过期的就删除;或者临时上载文件存放表,每天只允许保留N个文件,过期的就连文件一起删除(数据库存放文件路径方式,除了删除记录,还要删除文件——意味着需要取出将被删除的过期记录)。
因为事先不知道总记录长度,常规做法应该select count(*)一遍,然后获得要删除的记录条数。
不过为了提高数据库性能,应尽量减少查询结果返回次数——其实就是能不能一句SQL搞定?
- //删除记录,假设N为100
- DELETE FROM table WHERE id NOT IN ( SELECT id FROM table ORDER BY id DESC LIMIT 100 );
-
- //取出过期记录
- SELECT * FROM table WHERE id NOT IN ( SELECT id FROM table ORDER BY id DESC LIMIT 100 );
标签:
SQL,
数据库遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Database, Technology | No Comments »
Posted by bianbian on 2007-03-17 07:55
本文Tags: php, PostgreSQL, 数据库, 类
实在受不了ADOdb之类的庞大库了,还有网上下的几个库也超级难用,我自己写了一个。只当简单的用,事务之类的我还没有用到,所以没有写进去。感兴趣的可以补充。好像里面的函数有些要php 4.2以上的。
使用示例:
- <?php
- $db = & new PostgreSQL();
- //single record:
- $record = & $db->query_first("SELECT * FROM table WHERE id=xxx");
- //many lines:
- if ($records = & $db->query_all("SELECT * FROM table WHERE id>xxx")) {
- foreach ($records as &$record) {
- ...
- }
- }
- $db->close();
- ?>
类的代码:
Read the rest of this entry »
标签:
php,
PostgreSQL,
数据库,
类遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Technology, php | 1 Comment »
Posted by bianbian on 2007-03-15 02:43
本文Tags: php, PostgreSQL, 数据库, 编码
php 5.2 PostgreSQL 8.1
数据库是用UTF8编码建的:
./createdb -E UNICODE xxxx
但是用php插入中文数据的时候会报错:
ERROR: invalid byte sequence for encoding “UTF8″ ….
看字面意思,好像是因为数据库是UTF8,而插入的数据不是UTF8导致的错误。到psql终端下:
# \encoding
UTF8
# show client_encoding;
UTF8
前面一个UTF8是数据库的编码,后一个表示客户端数据编码(就是插入数据的编码)。
怎么解决?
本问题已经解决,请参考这里:php用UTF-8编码总结
标签:
php,
PostgreSQL,
数据库,
编码遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Database, Technology, php | No Comments »
Posted by bianbian on 2007-03-12 05:35
本文Tags: pgAdmin, 数据库
想为了省事,没装PowerDesign,直接用了pgAdmin设计表。
我K,被它害死了:每个表每个字段有大写的都用了引号引起来。。。
导致的后果就是:拼SQL语句的时候必须也加上引号,不然每次都
ERROR:relocation [TableName] does not exist…..
于是简单的“insert into Table(Column1,Column2)...”必须写成“insert into "Table"("Column1", "Column2")....”
我说,还不如重新建表吧。。。K pgAdmin它大爷。。。。
标签:
pgAdmin,
数据库遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Database, Technology | No Comments »
Posted by bianbian on 2006-12-20 03:28
本文Tags: libpq, 数据库
看过长篇文档后,啥废话也不说了,来个实例总结:
- char *sql = "SELECT userid,password FROM users WHERE ....";
- PGconn *conn = PQconnectdb("host=localhost user=postgres password= dbname=db port=5432");
- if (PQstatus(conn) == CONNECTION_OK)
- {
- PQsetClientEncoding(conn, "UNICODE");
- PGresult *res = PQexec(conn, sql);
- if (res != null)
- {
- int status = PQresultStatus(res);
- if (status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK)
- {
- char *res_userid = PQgetvalue(res, 0, 0);
- char *res_password = PQgetvalue(res, 0, 1);
- ....
- }
- PQclear(res);
- }
- }
- PQfinish(conn);
标签:
libpq,
数据库遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in C/C++, Database, Technology | 2 Comments »
Posted by bianbian on 2006-12-15 05:51
本文Tags: 数据库
不过这是很老的开源项目了,2001以后都没有更新。。。。。我只是了解一下除了Java做连接池外还有没有其他办法。
[原创翻译] DBBalancer是数据库服务器和客户端(C/C++, TCL, Java JDBC, Perl DBI等)之间的中间层. 尽管目前只支持PostgreSQL, 但是这个架构以后可以推广到其他数据库. 它最大的优点(恕我直言 ;-))就是不需要改变任何一行现有代码, 因为负载均衡是在Postgres的协议层完成的.
DBBalancer有很多功能:
它是一个连接池…. 能完成负载均衡…. 数据库同步….. 而且能同时做这些事情.
http://dbbalancer.sourceforge.net/
[Original] DBBalancer is some sort of middleware that would sit in between of database clients, like C, C++, TCL, Java JDBC, Perl DBI, and a database server. Currently the only server supported is Postgres, but the architecture is open to embrace more servers in a future. One of his strongest (IMHO ;-)) points is that it can be tried or used without changing a line of the existing code, because the balancing is done at Postgres protocol level.
DBBalancer can do different things.
It’s a connection pool…
… a load balancer,
.. and a database replicator.
And can be used any combination of these things at the same time.
标签:
数据库遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Database, Technology | 1 Comment »
Posted by bianbian on 2006-11-19 05:30
本文Tags: PostgreSQL, 备份, 恢复, 数据库
备份:
./pg_dump -U 用户名 -c -Fp 数据库名 -f 文件.sql
恢复:
./psql -U 用户名 < 文件.sql
标签:
PostgreSQL,
备份,
恢复,
数据库遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Database, Technology | No Comments »
Posted by bianbian on 2006-10-27 01:40
本文Tags: PostgreSQL, 存储过程, 数据库
今天学会了用 PL/pgSQL 写 postgreSQL 的存储过程,网上资料实在少得可怜,唯一能搜到的一些还是抄来抄去的;还是翻postgresql的文档吧,把今天解决的问题说一下吧,希望对其他人有帮助。
问题是这样的,有一张message表:
CREATE TABLE message
(
id int8 NOT NULL,
receiveuserid int8,
senduserid int8,
receivedelete bool DEFAULT false,
senddelete bool DEFAULT false,
……
CONSTRAINT usermessage_pkey PRIMARY KEY (id)
)
略去其他字段,senduserid是发信息的用户id,senddelete如为true则表示这条消息被发信人所删除;至于receive我就不用说了。一条信息只有被发信人和收信人都删除,才能真正从表里删除(这是显然的,否则收信人删了一条消息后,发信人的“发件箱”里就会找不到这条消息)。
所以删除消息(可能是多条消息)的时候要进行各种判断(是否是发信人?是否是收信人?是否真正删除?),用单条SQL语句完成这个工作显然有些困难(当然用循环嵌套select不考虑效率的话也是可以实现的),只好写存储过程了。
顺便介绍常用的PL/pgSQL结构和语法吧:
- 结构
PL/pgSQL是一种块结构的语言,比较方便的是用pgAdmin III新建Function,填入一些参数就可以了。基本上是这样的:
CREATE OR REPLACE FUNCTION 函数名(参数1,[整型 int4, 整型数组 _int4, …])
RETURNS 返回值类型 AS
$BODY$
DECLARE
变量声明
BEGIN
函数体
END;
$BODY$
LANGUAGE ‘plpgsql’ VOLATILE;
- 变量类型
除了postgresql内置的变量类型外,常用的还有 RECORD ,表示一条记录。
- 赋值
赋值和Pascal有点像:“变量 := 表达式;”
有些奇怪的是连接字符串的是“||”,比如 sql := ‘SELECT * FROM’ || table || ‘WHERE …’;
- 判断
判断又和VB有些像:
IF 条件 THEN
…
ELSEIF 条件 THEN
…
ELSE
…
END IF;
- 循环
循环有好几种写法:
WHILE expression LOOP
statements
END LOOP;
还有常用的一种是:(从1循环到9可以写成FOR i IN 1..9 LOOP)
FOR name IN [ REVERSE ] expression .. expression LOOP
statements
END LOOP;
- 其他
还有几个常用的函数:
SELECT INTO record …; 表示将select的结果赋给record变量(RECORD类型)
PERFORM query; 表示执行query并丢弃结果
EXECUTE sql; 表示执行sql语句,这条可以动态执行sql语句(特别是由参数传入构造sql语句的时候特别有用)
最后,贴出解决上面这个问题的存储过程吧:
- CREATE OR REPLACE FUNCTION message_deletes(ids "varchar", userid int8)
- RETURNS int4 AS
- $BODY$
- DECLARE
- r RECORD;
- del bool;
- num int4 := 0;
- sql "varchar";
- BEGIN
- sql := 'select id,receiveuserid,senduserid,senddelete,receivedelete from message where id in (' || ids || ')';
- FOR r IN EXECUTE sql LOOP
- del := false;
- IF r.receiveuserid=userid and r.senduserid=userid THEN
- del := true;
- ELSEIF r.receiveuserid=userid THEN
- IF r.senddelete=false THEN
- update message set receivedelete=true where id = r.id;
- ELSE
- del := true;
- END IF;
- ELSEIF r.senduserid=userid THEN
- IF r.receivedelete=false THEN
- update message set senddelete=true where id = r.id;
- ELSE
- del := true;
- END IF;
- END IF;
- IF del THEN
- delete from message where id = r.id;
- num := num + 1;
- END IF;
- END LOOP;
- return num;
- END;
- $BODY$
- LANGUAGE 'plpgsql' VOLATILE;
测试使用:

标签:
PostgreSQL,
存储过程,
数据库遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Database, Technology | 1 Comment »
Posted by bianbian on 2006-09-19 02:27
本文Tags: PostgreSQL, 数据库
试了一会儿,先记下来。省得以后忘掉。
Well, the tables are: (tag的表情况,usertags表记录了每个用户的tag(一行记录一个tag),usersites表记录了每个url对应的多个tags,urltags表记录了一个usersiteid对应多个usertagid(反过来也是一个usertagid对应多个usersiteid))
- usertags usersites urltags
- =======================================================================
- id tagname userid id url title userid tags id usersiteid usertagid
now we need to get all tagnames, tagid, and used times of a tag, sorted by used times, how to do it? (现在我们需要一次查询得到所有的tagname、每个tag对应的tagid和使用次数并按使用次数排序)
SQL 语句如下:
- SELECT count(t.usersiteid) AS count, t.usertagid, n.tagname
- FROM urltags t, usertags n
- WHERE t.usertagid=n.id
- AND usertagid in ( select DISTINCT on (usertagid) usertagid from urltags )
- group by t.usertagid,n.tagname
- order by count DESC
中间的子查询“select DISTINCT on (usertagid) usertagid from urltags ”查询出所有对照表里的usertagid,其中DISTINCT on(usertagid)表示只查询出usertagid字段不重复的记录(即多个相同的usertagid值的话只取一个)。DISTINCT的写法可能只是postgreSQL的特殊函数,不过相信其他数据库应该也有不同写法的支持。
执行结果截图,应该是对的吧。。。。呵呵:

标签:
PostgreSQL,
数据库遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Database, Technology | No Comments »