Cover V03, I06
Figure 1
Figure 2
Listing 1
Listing 2
Sidebar 1


Sybase Database Administration: Part 2

William Genosa

Last issue (Sept/Oct '94) I gave a brief overview of Sybase and a detailed description of how Sybase catalogs the relationships between logical and physical disk devices. I discussed the disk init command and introduced the create.diskinit program that reverse-engineers the logical-to-physical relationships of Sybase disk devices. This month I will discuss database tables and provide two useful tools that generate the SQL required to recreate a single table, or all the tables in a Sybase database.

Sybase catalogs all the information about database objects in system tables (see Figure 1 for an example table), which are a part of each database. The create.table program (Listing 1) retrieves from system tables all the information required to generate the SQL. The SQL is used to recreate the table passed as the first argument to create.table. Figure 2 shows part of the five tables used by create.table. Because every Sybase database has a SYSSEGMENTS table, the entries in Figure 2 are for that table.

How create.table Works

The create.table program can be broken down into six sections. The first section sets up environment variables. If this program is executed alone, then you can set all environment variables within create.table. If you'll execute this program with other tools that require setting the same environment variables, section one's test sets them by using the dot command on a configuration file. The configuration file eliminates editing each program individually.

Section two checks the usage of create.table, ensuring that a table name is supplied for the first argument.

I will skip section three for a moment. Discussing section four is more meaningful now.

Section four is the heart of create.table: it queries the Sybase server to request column information on the table named in the first argument.

Every table within a database has a unique ID number assigned to it. That ID is used as the primary key for the system table, SYSOBJECTS, and as a foreign key in eight other system tables. The query in section four executes a subquery, which returns the object ID from SYSOBJECTS for the table named by argument one.

Every column in every table has an entry in the system table, SYSCOLUMNS. The query in section four joins the tables SYSCOLUMNS and SYSINDEXES, returning column names in terms of their relationship on the ID column, which was returned from the subquery discussed above.

Every column must also belong to one specific datatype. All datatypes are defined in the system table, SYSTYPES. The query in section four joins the tables SYSTYPES with SYSCOLUMNS, returning data type names in terms of their relationship on the usertype column. The length of each column is also returned.

As shown by the syntax of the CREATE TABLE statement, each column must be defined to either allow or disallow Null values on table creation. A Null represents the absence of a recorded value. This information is stored in the table SYSCOLUMNS as a bit value. The query in section four returns a zero if Nulls are not allowed and a one if Nulls are allowed.

Tables are database objects which are placed on segments. The query in section four joins the system table SYSSEGMENTS with the system table SYSINDEXES, returning the segment name in terms of their relationship on the segment column.

The columns returned from the query in section four are ordered by their colid. This guarantees that tables recreated with the SQL generated from the create.table program will restore columns in their original order.

Also note that the indid of SYSINDEXES must be less than two. Tables will always have an indid in SYSINDEXES of zero or one. An indid of one is assigned to clustered indexes. A clustered index is a special type of table.

The output of the query in section four is piped into awk. awk's BEGIN statement creates a header with SCCS keyword identifiers as well as the CREATE TABLE statement itself. awk checks each line for two criteria: first, whether Nulls are allowed for each column, and second, whether the data type is a char (character), because a char datatype must include the length. awk's END statement includes the segment where this table is to be placed, along with the SQL terminator, go. awk's output is saved in the file assigned to the variable QUERYOUT.

To return to section three, which I skipped earlier: the syntax of a CREATE TABLE statement must include a comma after each column except for the last column being created. Section three's function is to create a program that adds commas after all columns except the last. grep searches for the word Null to extract those lines that contain column information. The last column created will always be the fifth line from the last. A comma is placed after each column except for the last. Notice that because the variable LINES is assigned a number that is dependent on the result of a query to the Sybase server, the shell could not complete variable substitution if the create.table program were a single executable. Therefore, the program created in section three is saved and executed in section five, after the query has completed.

Section five executes the program created in section three. Section five's output is filtered to replace question marks with percent signs for the SCCS keywords. The idea here is to prevent the expansion of SCCS keywords when create.table is checked into SCCS. If the table was created on the default segment, it is also filtered out because default is implicit and Sybase does not allow you to explicitly specify default as a segment. Final output is left in the file assigned to the variable SQL.

Section six cleans up by removing files no longer needed.

Recreating All User Tables

The create.table program only generates the SQL to recreate a single table. Because I wanted to generate SQL to recreate all user tables in a database without losing the ability to generate the SQL for a single database table, I also wrote a program called create.table.all (Listing 2). create.table.all builds a list of all user tables in a database, executing create.table for each table named in the list. This is a perfect example of when to use the .config file for variable assignments.

When executed for a given database, create.table.all generates all SQL consistently.

About the Author

Bill Genosa is a UNIX Systems/Database Administrator with Harman Consumer Group, located in Woodbury, New York. He works with RS6000 computers on systems that serve some 150 users across the US and in Denmark and Singapore. You can reach Bill at 186 Bryant Avenue, Floral Park, NY 11001, or via email as