存档

2010年 的存档,文章数:148

问题描述:

在UNIX及某些系统内不能启动Sybase Center,那么在这种情况下怎样修改sa密码呢,同时如果我们不需要密码时也可以使用该方法将sa密码置为空。

如何将sa的密码置为空,假设当前sa密码为:123456。

解决方案:
$isql -Usa -P123456 -SSYBASE
1>sp_configure "upgrade version"
2>go
#记录打印的版本号,Run Value表示当前系统版本是:11920 (sybase 11.9.2)

1>sp_configure "upgrade version",492
2>go
#更改版本号为492

1>sp_password   '123456',NULL,sa
2>go
#修改密码将123456密码置为空

1>sp_configure "upgrade version",11920
2>go
#务必更改版本号为原来的版本号

如果将参数upgrade version修改为492后忘记改回原来的值,则在Sybase服务器关闭后再启动的时候报错:

Pre 10.0 database cannot work with this version of the server. Please upgrade the databases to 10.0 or above release and then try to start with this version of the server. Shutting down ***.

这说明master数据库已经损坏了。因此,通过修改参数upgrade version重置sa口令为空时千万要谨慎,最后一定要将upgrade version修改回原值!

修复的方法请参考:

master数据库配置区域(configuration area)损坏的一种修复方法

https://www.dbainfo.net/one-way-to-recover-master-configuration-area.htm

Sybase数据库技术,数据库恢复博客欢迎您的光临!

本博客旨在交流Sybase数据库使用心得、共享Sybase数据库技术知识。

期待与您交流Sybase或者其他数据库技术!

QQ :289965371 (晴空)

MSN:

在Sybase ASE中默认的情况是对象名或者字段名区分大小写,数据库内的字符按照二进制进行排序。单字节字符就按照字符的ASCII值排序,对于多字节(如:一个汉字)字符则是按照第一个字节的ASCII值进行排序。此时,汉字的排序是没有意义的。

但是,有时候会遇到要求对象名或者对象字段名不区分大小写的情况。比如:将其他rdbms的数据库移植到sybase ASE数据库(比如:ASA,oracle等);业务系统要求对象名不区分大小写等场景。

本文介绍在Sybase ASE 15.0.3中调整字符集和排序顺序使得ASE不区分对象名和字段名的大小写。

在谈到数据库的字符集时,不得不提到数据库的排序顺序。字符集和排序顺序的关系如此紧密,必须同时调整二者才能实现在ASE中不区分对象名的大小写。

ASE中的字符集有很多种,随着版本的升级,好像字符集种类也是越来越丰富。在ASE11.9.2版本中还没有支持简体中文的字符集cp936,仅有eucgb这个中文字符集。在最新的ASE15.x版本中,可以用作简体中文的字符集有:cp936,eucgb,gb18030,utf8;支持繁体中文的字符集有:cp950,big5,big5hk,euccns,utf8。如果仅仅需要支持简体中文的话,那么用cp936足够了。考虑ASE数据库支持国际化,则可选用utf8。

如何既支持简体中文又能容纳繁体中文呢?

对于此问题,我感觉应该用utf8字符集。因为在ASE中简体或者繁体中文分别有不同的字符集,只能选择一个最“包容”,范围最广的字符集:utf8。

转入正题:

我的测试环境安装的ASE字符集为:iso_1,默认的字符集排序顺序为:bin__iso_1。无论对象名还是对象内的数据,都是严格区分大小写的。

第一步:检查数据库内是否安装了不区分大小写的iso_1字符集。

select id,name from master..syscharsets where name like '%iso_1%'

查询结果为:

1> select id,name from master..syscharsets where name like '%iso_1%'
2> go
 id  name
 --- ------------------------------
 50 bin_iso_1
 1 iso_1
 
(2 rows affected)

说明数据库内安装有iso_1字符集和按照二进制值进行排序的bin_iso_1(排序顺序在其他rdbms中好像被称为collate,不太好翻译,有的翻译为“整理”,感觉很别扭。在mssqlserver和mysql中都有这个概念。)

第二步:安装不区分大小的iso_1的整理collate

切换到字符集目录下:

cd %sybase%\charsets\iso_1 (unix下位:cd $SYBASE/charsets/iso_1)

发现D:\sybase\charsets\iso_1中有几个*.srt文件,它们分别对应不同的“整理”--排序顺序。

D:\sybase\charsets\iso_1>dir *.srt
 驱动器 D 中的卷没有标签。
 卷的序列号是 24C3-2A76
 
 D:\sybase\charsets\iso_1 的目录
 
2004-11-02  02:13               656 binary.srt
2004-11-02  02:13             8,703 dictiona.srt
2004-11-02  02:13             8,703 dictionary.srt
2004-11-02  02:13             8,669 espdict.srt
2004-11-02  02:13             8,682 espnoac.srt
2004-11-02  02:13             8,584 espnocs.srt
2004-11-02  02:13             8,738 noaccent.srt
2004-11-02  02:13             8,738 noaccents.srt
2004-11-02  02:13             9,209 nocase.srt
2004-11-02  02:13             9,312 nocasepr.srt
2004-11-02  02:13             9,312 nocasepref.srt
 11 个文件         89,306 字节
 0 个目录 17,730,179,072 可用字节
 
D:\sybase\charsets\iso_1>

其中:binary.srt表示二进制排序,dictiona.srt表示按照字典顺序,nocase.srt表示不区分大小的排序(具体的还有:nocasepr.srt,nocasepref.srt,好像是dictionary order,case insensitive with preference,具体没有细研究!)

本文的场景需要nocase.srt这个。

安装nocase.srt这个排序顺序(“整理”)

charset -Usa -P -Stest nocase.srt iso_1

D:\sybase\charsets\iso_1>charset -Usa -P -Stest nocase.srt iso_1
Loading file 'nocase.srt'.
 
Found a [sortorder] section.
 
This is Class-1 sort order.
 
Character set for the sort order is already in the Syscharsets table.
 
Sort order (ID = 52 ,CSID = 1 ) with NAME = 'nocase_iso_1' already exists
in the Syscharsets system table.  Do you wish to update this sort order
with the definitions found in your localization file for sort order
(ID = 52, CSID = 1, NAME = 'nocase_iso_1')?
(yes/no):  yes
 
Finished loading file 'nocase.srt'.
 
1 sort order loaded successfully

第三步:在ASE中配置数据库的排序顺序。

首先,检查ASE当前的排序顺序,用sp_helpsort这个系统存错过程。在输出结果的Sort Order Description部分,看到有:

Sort Order Description
 
 ------------------------------------------------------------------
 Character Set = 1, iso_1
 ISO 8859-1 (Latin-1) - Western European 8-bit character set.
 Sort Order = 50, bin_iso_1
 Binary ordering, for the ISO 8859/1 or Latin-1 character set (
 iso_1).
Characters, in Order

可看出当前排序顺序为:区分大小写的二进制顺序bin_iso_1。

利用如下的SQL语句检查刚才安装的nocase.srt排序顺序在syscharsets表中对应的id值。

select id,name from master.dbo.syscharsets where name like '%iso_1%'

1> select id,name from master.dbo.syscharsets where name like '%iso_1%'
2> go
 id  name
 --- ------------------------------
 50 bin_iso_1
 1 iso_1
 52 nocase_iso_1
 
(3 rows affected)
1>

刚才安装的不区分大小写的排序对应ID为:52。

利用系统存储过程sp_configure 修改默认排序顺序,执行: sp_configure  "default sortorder id",52

执行完毕后,需要重启启动ASE两次(这和改字符集的时候是一样的,)。

ASE启动之后,用sp_configure  "default sortorder id"检查,当前排序顺序值为:52.

用sp_helpsort检查,Sort Order Description部分的信息为:

Sort Order Description
 
 ------------------------------------------------------------------
 Character Set = 1, iso_1
 ISO 8859-1 (Latin-1) - Western European 8-bit character set.
 Sort Order = 52, nocase_iso_1
 Case-insensitive dictionary sort order for use with several We
 stern-European languages including English, French, and German
 .  Uses the ISO 8859-1 character set.
Characters, in Order

发现,已经修改完成了。下面做个试验测试一下。

1> use andkylee
2> go
1> create table ANDKylee(ID int not null,NaMe varchar(30) null)
2> go
1> create table andkylee(id int not null,name varchar(30) null)
2> go
Msg 2714, Level 16, State 1:
Server 'TEST', Line 1:
There is already an object named 'andkylee' in the database.
1> insert into ANDKYLEE values(1,'aaaa')
2> insert into andkylee values(1,'AAAA')
3> insert into aNDKYLEE values(2,'bbBB')
4> insert into andkyLEE values(2,'BBbb')
5> go
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
1> select *  from andkyLEE where name='AAAA'
2> go
 ID          NaMe
 ----------- ------------------------------
 1 aaaa
 1 AAAA
 
(2 rows affected)
1> select *  from andkylee where name='aaaa'
2> go
 ID          NaMe
 ----------- ------------------------------
 1 aaaa
 1 AAAA
 
(2 rows affected)
1> select *  from andkylee where name='BbBb'
2> go
 ID          NaMe
 ----------- ------------------------------
 2 bbBB
 2 BBbb
 
(2 rows affected)
1> select *  from ANDKYLEE order by name
2> go
 ID          NaMe
 ----------- ------------------------------
 1 AAAA
 1 aaaa
 2 BBbb
 2 bbBB
 
(4 rows affected)
1>

可以发现,对象名,字段名,还有表内的数据都不区分大小写了。

最后强调两点:

1.改成不区分大小写的排序顺序要慎重。对象名或者字段名不区分大小写可能问题不多,需要慎重考虑表内数据是否真正地不区分大小写。

2.最好在刚安装完ASE数据库服务器后修改数据库的排序顺序,或者确保各个库内已有的对象名在不区分大小写后是唯一的。我在测试的时候遇到在转化后即将导致sysobjects索引键冲突而失败的情况。

用户库andkylee内原来用testA和testa两种表,在转化的过程报如下的错误:

00:00000:00001:2010/09/06 11:26:34.59 server  Rebuilding indexes for andkylee..sysobjects.
00:00000:00001:2010/09/06 11:26:34.70 server  Error: 1505, Severity: 16, State: 2
00:00000:00001:2010/09/06 11:26:34.71 server  Create unique index aborted on duplicate key.  Primary key is '"testa", 1'
00:00000:00001:2010/09/06 11:26:34.76 server  Error: 3436, Severity: 20, State: 2
00:00000:00001:2010/09/06 11:26:34.76 server  Cannot rebuild index 2 for the 'sysobjects' table in the 'andkylee' database.
00:00000:00001:2010/09/06 11:26:34.76 server  Error: 3434, Severity: 20, State: 1
00:00000:00001:2010/09/06 11:26:34.76 server  Cannot change sortorder. Server shutting down.  Restart to continue with sortorder unchanged.
00:00000:00001:2010/09/06 11:26:34.76 kernel  ueshutdown: exiting
 
 

有问题,欢迎讨论!

————————————————————————————————————
——— 本文为andkylee个人原创,请在尊重作者劳动成果的前提下进行转载;
——— 转载务必注明原始出处 : http://www.dbainfo.net
——— 关键字: ASE 字符集 排序顺序 iso_1 nocase_iso_1 sp_helpsort default sortorder id
————————————————————————————————————

  一、使用 Microsoft OLE DB Provider For ODBC 链接MySQL 
  安装MySQL的ODBC驱动MyODBC
1、为MySQL建立一个ODBC系统数据源,例如:选择数据库为test ,数据源名称为myDSN
2、建立链接数据库
  EXEC sp_addlinkedserver @server = ’MySQLTest’, @srvproduct=’MySQL’,
  @provider = ’MSDASQL’, @datasrc = ’myDSN’
  GO
  EXEC sp_addlinkedsrvlogin
  @rmtsrvname=’MySqlTest’,@useself=’false’,@locallogin=’sa’,@rmtuser=’mys
  ql的用户名’,@rmtpassword=’mysql的密码’
3、查询数据
  SELECT * FROM OPENQUERY (MySQLTest ,’select * from 表’ )
  下面这个不行:
  SELECT * FROM OPENQUERY (MySQLTest ,’表’ )
  注意:不能直接用select * from 链接服务器名.数据库名.用户名.表(或视图)
  四部分名称查询数据,可能是个Bug.
二、使用 Microsoft OLE DB Provider For ORACLE 链接ORACLE
1、建立链接数据库
 sp_addlinkedserver ’别名’, ’Oracle’, ’MSDAORA’, ’服务名’
  GO
 EXEC sp_addlinkedsrvlogin @rmtsrvname=’别名 ’,@useself=’false’,@locallogin=’sa’,@rmtuser=’oracle用户名 ’,@rmtpassword=’密码’
2、查询数据
  SELECT * FROM 别名..用户名.表(视图)
  注意:四部分名称全部用大写
3、执行存储过程
  使用OPENQUERY:
  SELECT *
  FROM OPENQUERY(别名, ’exec 用户名.存储过程名’) 
    
三、设置链接服务器以访问格式化文本文件
  用于 Jet 的 Microsoft OLE DB 提供程序可用于访问并查询文本文件。
    若要直接创建访问文本文件的链接服务器而不将文件链接为 Access .mdb 文件中的表,请行 sp_addlinkedserver,如下例所示。
  提供程序是 Microsoft.Jet.OLEDB.4.0,提供程序字符串为"Text"。数据源是包含文本文件的目录的完整路径名称。 schema.ini 文件(描述文本文件的结构)必须与此文本文件存在于相同的目录中。有关创建 schema.ini 文件的更多信息,请参见 Jet 数据库引擎文档。
  --Create a linked server.
  EXEC sp_addlinkedserver txtsrv, ’Jet 4.0’,
  ’Microsoft.Jet.OLEDB.4.0’,
  ’c:\data\distqry’,
  NULL,
  ’Text’
  GO
  --Set up login mappings.
  EXEC sp_addlinkedsrvlogin txtsrv, FALSE, NULL, Admin, NULL
  GO
  --List the tables in the linked server.
  EXEC sp_tables_ex txtsrv
  GO
  --Query one of the tables: file1#txt
  --using a 4-part name.
  SELECT *
  FROM txtsrv...[file1#txt]
  四、链接SQL Server服务器: 
1、使用 ODBC 的 Microsoft OLE DB 提供程序 
  EXEC sp_addlinkedserver ’别名’,’’,’MSDASQL’,NULL,NULL,’DRIVER={SQL  Server};SERVER=远程名;UID=用户;PWD=密码;’ 
  如果加上参数@catalog,可以指定数据库 
  exec sp_addlinkedsrvlogin @rmtsrvname=’别名  ’,@useself=’false’,@locallogin=’sa’,@rmtuser=’sa’,@rmtpassword=’密码’ 
2、使用SQL Server 的 Microsoft OLE DB 提供程序 
  exec sp_addlinkedserver @server=’别名  ’,@provider=’sqloledb’,@srvproduct=’’,@datasrc=’远程服务器名’ 
  exec sp_addlinkedsrvlogin 
  @rmtsrvname=’wzb’,@useself=’false’,@locallogin=’sa’,@rmtuser=’sa’,@rmtp 
  assword=’密码’ 
  然后你就可以如下: 
  select * from 别名.库名.dbo.表名 
  insert 库名.dbo.表名 select * from 别名.库名.dbo.表名 
  select * into 库名.dbo.新表名 from 别名.库名.dbo.表名 
  go 
  例1、 
  此示例在 SQL Server 的实例上创建一台名为 S1_instance1 的链接服务器, 
  该服务器使用 SQL Server 的 Microsoft OLE DB 提供程序。  EXEC sp_addlinkedserver @server=’S1_instance1’, @srvproduct=’’,  @provider=’SQLOLEDB’,  @datasrc=’S1\instance1’ 
  例2、 
  --建立链接服务器 
  EXEC sp_addlinkedserver ’xiaoming’,’’,’MSDASQL’,NULL,NULL,’DRIVER={SQL 
  Server};SERVER=192.168.0.1;UID=sa;PWD=123;’ 
  --建立链接服务器登录映射 
  exec sp_addlinkedsrvlogin 
  @rmtsrvname=’xiaoming’,@useself=’false’,@locallogin=’sa’,@rmtuser=’sa’, 
  @rmtpassword=’123’ 
  go 
  --查询数据 
  select * from xiaoming.schooladmin.dbo.agent 
  --删除链接服务器登录映射和链接服务器: 
  exec sp_droplinkedsrvlogin ’xiaoming’ ,’sa’ 
  exec sp_dropserver ’xiaoming’ 
  注意事项: 
  SET IDENTITY_INSERT [ database.[ owner.] ] { table } { ON | OFF } 
  所以不能通过连接服务器设置此属性 
  into 也存在这样的问题 
  select * into xiaoming.northwind.dbo.tt from 
  xiaoming.northwind.dbo.tt

五、设置链接服务器以访问Access数据库
  使用用于 Jet 的 Microsoft OLE DB 提供程序
  此示例创建一台名为 test的链接服务器。
  说明 本示例假设已经安装 Microsoft Access 和示例 Northwind 数据库,且
  Northwind 数据库驻留在 C:\。
  USE master
  GO
  -- To use named parameters:
  EXEC sp_addlinkedserver
  @server = ’test’,
  @provider = ’Microsoft.Jet.OLEDB.4.0’,
  @srvproduct = ’OLE DB Provider for Jet’,
  @datasrc = ’C:\Northwind.mdb’
  GO
  -- OR to use no named parameters:
  USE master
  GO
  EXEC sp_addlinkedserver
  ’test’,
  ’OLE DB Provider for Jet’,
  ’Microsoft.Jet.OLEDB.4.0’,
  ’C:\Northwind.mdb’
  GO
  使用
  select * from test...表名

六、连接SYBASE
  --首先,你要在SQL服务器上装上访问sybase的客户端
  --创建链接服务器
  exec sp_addlinkedserver ’Sybase1’, ’ ’, ’MSDASQL’, NULL, NULL
  ,’Driver={Sybase System
  11};Database=hisdb;Srvr=10.211.135.12;UID=sa;PWD=1111;’
  使用:
  select * from Sybase1.hisdb.dbo.table1
  方法二
  使用ODBC
  SQL Server到SYBASE连接服务器的实现
  作者: CCBZZP
  本文的测试环境为:
  操作系统: WINDOWS2000 SERVER (繁体系统)
  安装数据库: SQLSERVER2000(英文版)和SYBASE8.0客户端(英文版)
  具体实现步骤:
  1.要求pc机上安装SYBASE8.0客户端软件和sqlserver2000软件。
  2.配置windows的ODBC数据源:
  开始菜单—》程式集—》系统管理工具—》资料数据源(ODBC)—》进入配置用户DSN或者系统DSN均可以:添加—》选择 ADAPTIVE SERVER ANYWHERE8.0—》自定义数据源名称(随意如: SYBASETEST)—》数据库名称(必选!)—》OK完成。
  3. 选择刚才配置的数据源名称, 再选择 配置, 跳出SYBASETEST MESSAGES:
  The data source is not connected. Connecting to the data source will
  provide useful information during configuration. Would you like to
  connect to the data source?
  选择YES(OK或确认)即可
  进入CONNECT TO SYBASE DATABASE画面:
  USER ID: 输入SYBASE DATABASE的用户
  PASSWORD: 输入SYBASE DATABASE的用户的密码
  CONNECTION MODE: 可以选择默认的SHARE模式
  选择OK(确认)即可!
  配置和测试ODBC完成!
  4.配置sqlserver2000中的连接服务器:
  企业管理器—》安全性—》连接服务器—》右键新建连接服务器—》定义连接名称; 选其他数据源; 指定程序名称为:SYBASE ADAPTIVE SERVER ANYWHERE PROVIDER8.0; 产品名称可不填; 数据源指定刚才ODBC中定义好的数据源名称;提供程序字符串按以下格式填写:User ID=username;Password=userpasswd(或者按如下格式:UID=username;PWD=userpasswd),这里的用户名和密码对应所要连接的SYBASE数据库中的用户名和密码 —》 安全性标签页里:设置用此安全上下文进行,并录入SYBASE的数据库用户名和密码—》服务器选项标签页可默认—》确定。
  5.准备工作全部完成!在 sqlserver企业管理器—》安全性—》连接服务器打开刚建好的连接服务器—》点击表,即可在右边窗口看到该SYBASE数据库用户拥有的所有表名,但在这里还并不能查看表的记录,这个需要在sqserver的查询分析器中用具体sql实现!访问表时,使用格式为: [连接服务器名].. [SYBASE用户].[表名]。

oracle的版本为:10gr2,10.2.0.1.0。

利用oracle中的hsodbc连接sqlserver2005数据库。已成功连接。db link的名字为: sql2005fororacle。

执行:select count(*) from sysdatabases@sql2005fororacle; 能够成功执行。

但是,在执行: select count(*) from sysobjects@sql2005fororacle;却导致系统出现了死机症状,无法响应任务的操作,任务管理器看到cpu利用率不高。无奈,只能强制关机。

在alert_<SID>.log文件中发现有这么几句:

Memory Notification: Library Cache Object loaded into SGA
Heap size 2225K exceeds notification threshold (2048K)
KGL object name :XDB.XDbD/PLZ01TcHgNAgAIIegtw==

原来遇到oracle的bug了。上网检索,说 是oracle的一个bug在10g10.2.0.1的各个平台上都出现过。 Oracle10g中,在load较大的对象进library cache中时,会记录以上警告。在版本10.2.0.1中,这个定义大对象的阈值是2M,这是有隐含参数 _kgl_large_heap_warning_threshold 指定的从10.2.0.2起,这个参数的默认值被修改为50M。

解决方法1 :升级到10.2.0.2或者以上。

解决方法2

SQL> alter system set "_kgl_large_heap_warning_threshold"=20388608 scope=spfile ;
SQL> shutdown immediate

SQL> startup

或者将 2038860调成更大的值。

我是通过调整隐式参数的方式解决的,重启后。

下面就是在oracle中访问sqlserver2005数据库的数据的效果:

SQL> select "name" from sysobjects@sql2005fororacle where "type"='U';
name
--------------------------------------------------------------------------------
spt_fallback_db
spt_fallback_dev
spt_fallback_usg
QuestSoftwareProc
pbcattbl
pbcatcol
pbcatfmt
pbcatvld
pbcatedt
spt_monitor
spt_values
name
--------------------------------------------------------------------------------
MSreplication_options
已选择12行。
SQL> desc sysusers@sql2005fororacle
 名称                                      是否为空? 类型
 ----------------------------------------- -------- ----------------------------
 uid                                                NUMBER(5)
 status                                             NUMBER(5)
 name                                      NOT NULL VARCHAR2(128 CHAR)
 sid                                                RAW(85)
 roles                                              RAW(2000)
 createdate                                NOT NULL DATE
 updatedate                                NOT NULL DATE
 altuid                                             NUMBER(5)
 password                                           RAW(256)
 gid                                                NUMBER(5)
 environ                                            VARCHAR2(32512 CHAR)
 hasdbaccess                                        NUMBER(10)
 islogin                                            NUMBER(10)
 isntname                                           NUMBER(10)
 isntgroup                                          NUMBER(10)
 isntuser                                           NUMBER(10)
 issqluser                                          NUMBER(10)
 isaliased                                          NUMBER(10)
 issqlrole                                          NUMBER(10)
 isapprole                                          NUMBER(10)
SQL>

在Sybase中,表内新添加的列都位于表的最后。其它数据库也基本相同,这和数据库的内部物理存储是有必然关系的。我研究过sybase 中数据的物理存储结构,理解在sybase以及其它数据库中新增加的列必须放置在最后的原因。 在项目实践中,可能有这样的需求:需要将最后添加的一列放置到前面的位置。比如:表test中原来的列为:a,b,c,不想让最后添加的列d放在第四个位置,而让列d放在第2个位置,形成:a,d,b,c这样的顺序。如何实现呢? 一般的办法是: 1.新建一个临时表:test_bak,

create table test_bak ( a 列属性,

d 列属性,

b 列属性,

c 列属性

)
 

2.将原表test的数据拷贝到临时表test_bak中

insert into test_bak(a,d,b,c)

select a,d,b,c from test
 

3.将原表删除,临时表改名为原表的名字

drop table test

sp_rename test_bak,test
 

以上是常规的办法。如果表内的数据量很大的时候,则会比较耗费时间。 下面我介绍另外一个比较简便的方法。

主要思路是调整表在syscolumns中对应的colid的值。

先建立一个新的测试表test

1> drop table test

2> go

1> create table test(id int not null,name varchar(30) null,age tinyint not null, se_x char(1) not null,birthday datetime null)

2> go

1> select *  from test
2> go
id          name                           age se_x birthday
----------- ------------------------------ --- --- --------------------------

(0 rows affected)

插入一条测试数据

1> insert into test
2> values(1,'andkylee',28,'F','1982-03-20 12:00:00')
3> go
(1 row affected)
1> select *  from test
2> go
id          name                           age se_x birthday
----------- ------------------------------ --- --- --------------------------
           1 andkylee                        28 F          Mar 20 1982 12:00PM
(1 row affected)

调整各个的顺序,使之倒序。将原来的id,name,age,se_x,birthday改成:birthday,se_x,age,name,id
调整方法:修改syscolumns表中测试表test的各个列的colid的顺序。

1> select *  from test
2> go
birthday                   se_x age name                           id
-------------------------- --- --- ------------------------------ -----------
        Mar 20 1982 12:00PM F    28 andkylee                                 1

(1 row affected)

列的顺序逆序后,显示插入数据。
 

1> insert into test(id,name,age,se_x,birthday)
2> values(2,'liu',30,'M','2000-01-01 11:59:59')
3> go
(1 row affected)
1> select * from test
2> go
birthday                   se_x age name                           id
-------------------------- --- --- ------------------------------ -----------
        Mar 20 1982 12:00PM F    28 andkylee                                 1
        Jan  1 2000 11:59AM M    30 liu                                      2

(2 rows affected)

如果按照调整数据之前的列的顺序插入数据,则会报错。

1> insert into test
2> values(3,'zhang',29,'F','1980-01-01 11:59:59')
3> go

Msg 206, Level 16, State 2:
Server 'SYB_NFJD_TEST', Line 1:
Operand type clash: INT is incompatible with DATETIME
Msg 257, Level 16, State 1:
Server 'SYB_NFJD_TEST', Line 1:
Implicit conversion from datatype 'VARCHAR' to 'INT' is not allowed.  Use the
CONVERT function to run this query.

新的数据要按照修改后的列的顺序插入。

1> insert into test
2> values('1980-01-01 11:59:59','F',29,'zhang',3)
3> go
(1 row affected)

最后,查看测试表的数据。

1> select * from test
2> go
birthday                   se_x age name                           id
-------------------------- --- --- ------------------------------ -----------
        Mar 20 1982 12:00PM F    28 andkylee                                 1
        Jan  1 2000 11:59AM M    30 liu                                      2
        Jan  1 1980 11:59AM F    29 zhang                                    3

(3 rows affected)

备注:绝大多数sybase客户端工具显示表的列时都是按照colid的顺序显示的。所以,此种方法能够实现调整数据库表中列的位置的功能。

————————————————————————————————————
——— 本文为andkylee个人原创,请在尊重作者劳动成果的前提下进行转载;
——— 转载务必注明原始出处 : http://www.dbainfo.net
——— 关键字: 列显示顺序 syscolumns colid
————————————————————————————————————

dbcc writepage是sqlserver 2000 和 2005中未公开的命令,也就是说使用这些未官方支持的命令出现的任何后果与MS无关。

同样,本文仅仅演示dbcc writepage的使用,您在操作时出现的任何后果与本人无关。

dbcc writepage的语法为:

   dbcc writepage ({ dbid, ‘dbname’ }, fileid, pageid, offset, length, data)

下面演示dbcc writepage的使用方法:

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

第一步:创建一个测试表

1> create table test (id int not null,name varchar(30) null)
2> go
1> insert into test
2> select 1,'china'
3> go

(1 行受影响)
1> insert into test
2> select 2,'beijing'
3> go

(1 行受影响)

 

1> select object_id('test')
2> go

-----------
 1877581727

(1 行受影响)

表的ID为: 1877581727。


第二步:查看表内数据所在的页面号

1> select * from sysindexes
2> where id = 1877581727
3> go
id          status      first    indid  root     minlen keycnt groupid dpages
   reserved    used        rowcnt               rowmodctr   reserved3 reserved4
xmaxlen maxirow OrigFillFactor StatVersion reserved2   FirstIAM impid  lockflags
 pgmodctr    keys
                                                                name

                                 statblob

                                                    maxlen      rows
----------- ----------- -------- ------ -------- ------ ------ ------- ---------
-- ----------- ----------- -------------------- ----------- --------- ---------
------- ------- -------------- ----------- ----------- -------- ------ ---------
 ----------- -------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------- ----------------
--------------------------------------------------------------------------------
-------------------------------- -----------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------- ----------- -----------
 1877581727           0 0x3B4F00       0 0x000000      8      0       1
 1           2           2                    2           2         0         0
     57       0              0           0           0 0x3C4F00      0         0
           0 NULL
                                                               NULL

                                 NULL

                                                           8000           2

(1 行受影响)


查询属于test表的第一个数据页的页号,在sysindexes表中first列表示对象的第一个物理存储页的页号:0x384F00,也就是页号(1:20283)。

 

第三步:查询修改前的数据内容

下面查询修改前页面(1,20283)上的数据内容。可以看出(1,20283)页上有2行记录,这和插入的2行记录数保持一致。然后,观察到页面的头部有china和beijing的字样,

这和插入的2行记录内容“似乎”一致。


下面我用红色标记了test表中两行测试数据的内容。1,'china'    2,'beijing'

1> dbcc page(9,1,20283,2)
2> go

DATA:
Memory Dump @0x518FC000

518FC000:   01010400 00800001 00000000 00000800 ?................

518FC010:   00000000 00000200 aa000000 721f8a00 ?............r...

518FC020:   3b4f0000 01000000 92010000 75000000 ?;O..........u...

518FC030:   02000000 00000000 00000000 00000000 ?................

518FC040:   01000000 00000000 00000000 00000000 ?................

518FC050:   00000000 00000000 00000000 00000000 ?................

518FC060:   30000800 01000000 0200fc01 00140063 ?0..............c

518FC070:   68696e61 30000800 02000000 0200fc01 ?hina 0...........

518FC080:   00160062 65696a69 6e670000 21212121 ?...beijing ..!!!!

518FC090:   21212121 21212121 21212121 21212121 ?!!!!!!!!!!!!!!!!

518FC0A0:   21212121 21212121 21212121 21212121 ?!!!!!!!!!!!!!!!!

........... 这些是未分配使用的空间

518FDFC0:   21212121 21212121 21212121 21212121 ?!!!!!!!!!!!!!!!!

518FDFD0:   21212121 21212121 21212121 21212121 ?!!!!!!!!!!!!!!!!

518FDFE0:   21212121 21212121 21212121 21212121 ?!!!!!!!!!!!!!!!!

518FDFF0:   21212121 21212121 21212121 74006000 ?!!!!!!!!!!!!t.`.

OFFSET TABLE:

Row - Offset

1 (0x1) - 116 (0x74)

0 (0x0) - 96 (0x60)

DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

 

第四步:修改物理数据页面的内容

通过上面的dbcc page输出结果,仔细数了一下,china这列内容的偏移为111,将china这五个字符改成aaaa。这是最简单的。a的asicc为:97(0x61)。

1> db cc writepage(9,1,20283,111,5,0x6161616161)
2> go
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

 

第五步:查看修改后的物理页面的内容

1> dbcc page(9,1,20283,2)
2> go

DATA:
Memory Dump @0x5002C000

5002C000:   01010400 00820001 00000000 00000800 ?................

5002C010:   00000000 00000200 aa000000 721f8a00 ?............r...

5002C020:   3b4f0000 01000000 92010000 75000000 ?;O..........u...

5002C030:   02000000 00000000 00000000 8234666e ?.............4fn

5002C040:   00000000 00000000 00000000 00000000 ?................

5002C050:   00000000 00000000 00000000 00000000 ?................

5002C060:   30000800 01000000 0200fc01 00140061 ?0..............a

5002C070:   61616161 30000800 02000000 0200fc01 ?aaaa 0...........

5002C080:   00160062 65696a69 6e670000 21212121 ?...beijing ..!!!!

5002C090:   21212121 21212121 21212121 21212121 ?!!!!!!!!!!!!!!!!

5002C0A0:   21212121 21212121 21212121 21212121 ?!!!!!!!!!!!!!!!!

5002C140:   21212121 21212121 21212121 21212121 ?!!!!!!!!!!!!!!!!

5002C150:   21212121 21212121 21212121 21212121 ?!!!!!!!!!!!!!!!!

..................省略未占用空间

5002DFE0:   21212121 21212121 21212121 21212121 ?!!!!!!!!!!!!!!!!

5002DFF0:   21212121 21212121 21212121 74006000 ?!!!!!!!!!!!!t.`.

OFFSET TABLE:

Row - Offset

1 (0x1) - 116 (0x74)

0 (0x0) - 96 (0x60)

DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

 

第六步:通过客户端工具验证修改后的数据内容

1> select * from test
2> go
id          name
----------- ------------------------------
          1 aaaaa
          2 beijing

(2 行受影响)
可以看到第一行记录的name列由china改为了aaaaa

备注: 以上演示的是仅仅修改某一行某一列的数据,并且修改后的内容和修改前的内容保持长度一致。

如果修改多列或者修改前后的字段长度不一致;进一步修改整行数据,或者修改整页的数据的话,可能会复杂许多。

————————————————————————————————-
—- 本文为andkylee个人原创,请在尊重作者劳动成果的前提下进行转载;
—- 转载务必注明原始出处 : http://www.dbainfo.net
—- 关键字:dbcc writepage undocumented command 修改 物理页面 page
————————————————————————————————-

在ASE中统计某个用户表的信息,比如:表中的行数、分配的空间、数据所占空间、索引所占空间以及剩余空间等,我们可以使用系统存储过程sp_spaceused来实现。

系统存储过程sp_spaceused有两个参数:@objname和@list_indices,第一个@objname是待统计的对象名,一般 是表名;第二个@list_indices标志是否单独统计索引信息,@list_indices=1表示单独统计索引信 息,@list_indices=0则不单独统计。

示例:

1> sp_spaceused sysobjects,0
2> go
 name       rowtotal reserved data   index_size unused
 ---------- -------- -------- ------ ---------- ------
 sysobjects 1014     252 KB   132 KB 68 KB      52 KB
(1 row affected)
(return status = 0)
1> sp_spaceused sysobjects,1
2> go
 index_name   size  reserved unused
 ------------ ----- -------- ------
 ncsysobjects 48 KB 64 KB    16 KB
 csysobjects  20 KB 32 KB    12 KB
(1 row affected)
 name       rowtotal reserved data   index_size unused
 ---------- -------- -------- ------ ---------- ------
 sysobjects 1014     252 KB   132 KB 68 KB      52 KB
(return status = 0)
1>

但是利用sp_spaceused还不能实现统计某个库里面哪张表的数据记录数最多,哪张表占用的空间最大,哪些表的行数为0,以及哪些表的索引所占空间大于100M等等的问题。

如何实现呢?

方法一:改造sp_spaceused过程语法中的SQL语句。但是,sp_spaceused过程的源代码有560多行,看起来比较累,至少需要一个临时表存储中间临时数据。


方法二:是本博客专门推荐使用的,利用ASE中的代理表来实现。下面是操作步骤:

假设用户数据库名字为:andkylee

先执行:use andkylee

            go

 

步骤一:建立代理表tablespace2

create  existing table tablespace2(name varchar(128) null,rowtotal char(15) ,reserved char(15),[data] char(15),index_size char(15),unused char(15),_objname varchar(128) null,_list_indices int null) external procedure at "loopback.andkylee.dbo.sp_spaceused"

代理表的列 有:name,rowtotal,reserved,data,index_size,unused,_objname,_list_indices,其 中name,rowtotal,reserved,data,index_size,unused这几列接收存储过程sp_spaceused返回的结果 数据。

注意name,rowtotal,reserved,data,index_size,unused的各列的数据类型要和sp_spaceused返回的列的类型一致。

_objname,_list_indices 是过程sp_spaceused的参数列。

需要再sysservers中加入一个指向自己的远程服务器loopback。

sp_addserver loopback,null,@@servername
go

如果@@servername为空,则写dsedit中显示服务器名。

 

步骤二:在代理表tablespace2上建立视图,统计库内所有用户表的存储空间

create view TableSize(name,rowtotal,reserved,data_KBytes,index_size,unused)
as
select name,cast(str_replace(rowtotal,' KB','') as int),cast(str_replace(reserved,' KB','') as int),cast(str_replace(data,' KB','') as int),cast(str_replace(index_size,' KB','') as int),cast(str_replace(unused,' KB','') as int) from tablespace2 where _list_indices  = 0
and _objname in
     (
        select user_name(uid)+"."+name from andkylee.dbo.sysobjects where type='U'
     )
go

说明:可以使用其它的条件来仅仅统计某些表,比如:只统计用户test所拥有的表的空间信息,那么改为: where type='U' and uid=user_id("test")


步骤三: 针对视图TableSize,根据要求写SQL语句

比如:统计记录数最多的10个表的表名、行数、分配空间,用如下的SQL:

select top 10 name,rowtotal,reserved  from TableSize order by rowtotal desc

go

1> select top 10 name,rowtotal,reserved  from TableSize order by rowtotal desc
2> go
 name
         rowtotal    reserved
 -------------------------------------------------------------------------------
-------------------------------------------------
         ----------- -----------
 SOS_Y_Hs_Xell
             1044911      178308
 test3
             1008576       21940
 test2
             1008576       21992
 SOS_Y_Wharehouse
              380000       31488
 SOS_Y_Hs_Xell_copy_1
              288097       49596
 FLOWREC1
              285139       40580
 PartitionTestTable
              262144       11368
 lzftest
              262144        7496
 SOS_Y_Hs_Xell_Back
              236000       40512
 SOS_R_Wharehouse
              192000       38408
(10 rows affected)

 

根据自己的要求写针对TableSize的相应的SQL语句,上面的sql在此抛砖引玉。

备注:

1、由于每次统计过程中都要涉及到待统计表的存储空间大小的计算,所以,上面介绍的方法对系统性能会有一点小的影响。只要不是频繁的执行,个人感觉影响可以忽略。

2、另外针对数据库日志也就是系统表syslogs的统计结果和其它表的不一样。

1> sp_spaceused syslogs
2> go
 name            total_pages     free_pages      used_pages
         reserved_pages
 --------------- --------------- --------------- ---------------
         ---------------
 syslogs         102400          101945          455
         0
(1 row affected)
(return status = 0)
1>

所以,不要在上面的被统计表中包含syslogs表。

————————————————————————————————-
—- 本文为andkylee个人原创,请在尊重作者劳动成果的前提下进行转载;
—- 转载务必注明原始出处 : http://www.dbainfo.net
—- 关键字:ASE sp_spaceused 代理表 存储过程 统计表的空间大小 行数最多的表的记录数

                 所占空间最大的表
————————————————————————————————-