#!/usr/bin/perl use strict; use DBI; use Getopt::Long 2.16; use POSIX; use Term::ReadKey 2.14; #*********************************************************************** # Local subroutines #*********************************************************************** sub escape_data($$); # escapes data for an SQL statement #*********************************************************************** # Package 'main' variables set by the mod_perl CGI environment #*********************************************************************** $ENV{ORACLE_HOME} = '/usr/oracle/app/oracle/product/8.0.5' if (! exists $ENV{ORACLE_HOME}); my $ORA_HOSTNAME; my $ORA_VERSION; my ($MAJOR_VERSION, $MINOR_VERSION) = q$Revision: 1.6 $ =~ /(\d+)\.(\d+)/; my $VERSION = sprintf("%d.%02d", $MAJOR_VERSION - 1, $MINOR_VERSION); my $dbh; # database handle my $sth; # statement handle my $table; # foreach loop iterator #*********************************************************************** # Parse command-line switches #*********************************************************************** my $opt_database; # database my @opt_tables; # tables my $opt_debug; # --debug my $opt_help; # -?|--help my $opt_complete_insert; # -c|--complete-insert my $opt_compress; # -C|--compress my $opt_extend_insert_insert; # -e|--extended_insert-insert my $opt_add_drop_table; # --add-drop-table my $opt_add_locks; # --add-locks my $opt_allow_keywords; # --allow-keywords my $opt_flush_logs; # -F|--flush-logs my $opt_force; # -f|--force my $opt_host; # -h|--host my $opt_lock_tables; # -l|--lock-tables my $opt_no_create_info; # -t|--no-create-info my $opt_no_data; # -d|--no-data my %opt_set_variable; # -O|--set-variable my $opt_opt; # --opt my $opt_password; # -p|--password my $opt_port; # -P|--port my $opt_quick; # -q|--quick my $opt_socket; # -S|--socket my $opt_tab; # -T|--tab my $opt_user; # -u|--user my $opt_verbose; # -v|--verbose my $opt_version; # -V|--version my @opt_where; # -w|--where my $opt_fields_terminated_by; # --fields-terminated-by my $opt_fields_enclosed_by; # --fields-enclosed-by my $opt_fields_optionally_enclosed_by; # --fields-optionally-enclosed-by my $opt_fields_escaped_by; # --fields-escaped-by my $opt_lines_terminated_by; # --lines-terminated-by my $help = <1" "-wuserid<1" Use -T (--tab=...) with --fields-... --fields-terminated-by=... Fields in the textfile are terminated by ... --fields-enclosed-by=... Fields in the importfile are enclosed by ... --fields-optionally-enclosed-by=... Fields in the i.file are opt. enclosed by ... --fields-escaped-by=... Fields in the i.file are escaped by ... --lines-terminated-by=... Lines in the i.file are terminated by ... Possible variables for option --set-variable (-O) are: MARK ## We want exact matches to the switches Getopt::Long::config('no_auto_abbrev', 'no_ignore_case'); my $rc = GetOptions( "debug=s" => \$opt_debug, "help|?" => \$opt_help, "c|complete-insert" => \$opt_complete_insert, "C|compress" => \$opt_compress, "e|extended_insert-insert"=> \$opt_extend_insert_insert, "add-drop-table" => \$opt_add_drop_table, "add-locks" => \$opt_add_locks, "allow-keywords" => \$opt_allow_keywords, "F|flush-logs" => \$opt_flush_logs, "f|force" => \$opt_force, "h|host=s" => \$opt_host, "l|lock-tables" => \$opt_lock_tables, "t|no-create-info" => \$opt_no_create_info, "d|no-data" => \$opt_no_data, "O|set-variable=s%" => \%opt_set_variable, "opt" => \$opt_opt, "p|password=s" => \$opt_password, "P|port=i" => \$opt_port, "q|quick" => \$opt_quick, "S|socket=i" => \$opt_socket, "T|tab=s" => \$opt_tab, "u|user=s" => \$opt_user, "v|verbose" => \$opt_verbose, "V|version" => \$opt_version, "w|where=s@" => \@opt_where, "fields-terminated-by=s" => \$opt_fields_terminated_by, "fields-enclosed-by=s" => \$opt_fields_enclosed_by, "fields-optionally-enclosed-by=s" => \$opt_fields_optionally_enclosed_by, "fields-escaped-by=s" => \$opt_fields_escaped_by, "lines-terminated-by=s" => \$opt_lines_terminated_by, ); $opt_database = shift @ARGV; # grab database name @opt_tables = splice(@ARGV, 0); # grab optional list of tables #*********************************************************************** # Process command-line switches #*********************************************************************** if (! $rc || defined $opt_help) { print STDERR $help; exit (defined $opt_help ? 0 : 1); } if (defined $opt_version) { print STDERR "oracledump v$VERSION\n"; exit 0; } ## After processing non-related switches, we *must* have a database defined if (! defined $opt_database) { print STDERR "ERROR: Must define database\n", $help; exit 1; } ## Define $opt_user if it wasn't set if (! defined $opt_user) { ($opt_user) = getpwuid($<); } ## Read password into $opt_password if it wasn't set if (! defined $opt_password) { print "Username: $opt_user\n"; ReadMode 'noecho'; print "Password: "; chop($opt_password = ); print "\n"; ReadMode 'restore'; } #*********************************************************************** # Connect to the database with $dbh #*********************************************************************** $dbh = DBI->connect("dbi:Oracle:$opt_database", $opt_user, $opt_password) || die "Cannot connect to database: $DBI::errstr"; #*********************************************************************** # Get list of tables if @opt_tables isn't set #*********************************************************************** if (scalar @opt_tables < 1) { my @row; $sth = $dbh->prepare("SELECT table_name FROM user_tables"); $sth->execute() || die $DBI::errstr; while (@row = $sth->fetchrow_array()) { push(@opt_tables, @row); } $sth->finish(); } #*********************************************************************** # Print out the header #*********************************************************************** ## Query Oracle for its instance hostname $sth = $dbh->prepare("SELECT HOST_NAME FROM V\$INSTANCE"); if ($sth->execute()) { ($ORA_HOSTNAME) = $sth->fetchrow_array(); } else { $ORA_HOSTNAME = ""; } $sth->finish(); ## Query Oracle for its version $sth = $dbh->prepare("SELECT banner FROM V\$VERSION WHERE UPPER(banner) LIKE 'ORA%'"); $sth->execute() || die $DBI::errstr; ($ORA_VERSION) = $sth->fetchrow_array(); $sth->finish(); ## Print header print <prepare("SELECT column_name, data_type, data_length, data_precision, data_scale, data_default, nullable FROM user_tab_columns WHERE table_name = ?"); $sth->execute(uc($table)) || die $DBI::errstr; my $c = 0; while (@row = $sth->fetchrow_array()) { $c++; printf(" %1s%-22s%-15s%-21s%-8s\n", ($c != 1 ? ',' : ' '), lc($row[0]), ($row[1] eq 'NUMBER' ? $row[1].'('.$row[3].', '.$row[4].')' : ($row[1] eq 'VARCHAR2' ? $row[1].'('.$row[2].')' : $row[1])), (defined $row[5] ? 'DEFAULT ' . $row[5] : ''), ($row[6] eq 'Y' ? '' : 'NOT NULL') ) if (! defined $opt_no_create_info); push(@column_types, $row[1]); } $sth->finish(); if (! defined $opt_no_create_info) { print < 0) ? "-- WHERE: " . join(' AND ', @opt_where) . "\n--\n" : "--\n" ]} MARK ## Generate list of column names $sth = $dbh->prepare("SELECT column_name FROM user_tab_columns WHERE table_name = ?"); $sth->execute(uc($table)) || die $DBI::errstr; while (@row = $sth->fetchrow_array()) { push(@column_names, @row); } $sth->finish(); ## Query for data then output SQL $sth = $dbh->prepare("SELECT @{[ join(',', @column_names) ]} FROM $table @{[ (scalar @opt_where > 0) ? ' WHERE ' . join(' AND ', @opt_where) : '' ]}"); $sth->execute() || die $DBI::errstr; while (@row = $sth->fetchrow_array()) { print <finish(); } } ## Print commit statement print <disconnect(); exit 0; #*********************************************************************** # Define local subroutines #*********************************************************************** sub escape_data($$) { my $type = shift; my $value = shift; if ($type eq 'NUMBER') { return $value; } elsif ($type eq 'VARCHAR2') { if (! defined $value) { return "NULL"; } else { $value =~ s/'/\\'/g; return "'$value'"; } } else { die "Unknown type: $type\n"; } } __END__ =pod =head1 NAME oracledump - dumps table data from Oracle in SQL script format =head1 SYNOPSIS oracledump [options] [
...] =head1 DESCRIPTION Dumps table data from Oracle in the format of an SQL script. Think I for Oracle. =over 4 =item This is the Oracle SID for the database, not the hostname. =item
[
...] This is a list of one or more table names. If no table names are listed, a list of all tables will be generated and used. =back =head1 TO DO The next major enhancement will be to dump SQL to recreate constraints, sequences, triggers and other table metadata. Please send comments, patches and suggestions to the email address below. =head1 SEE ALSO L, L =head1 COPYRIGHT Copyright (C) 1999 David Kilzer. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 AUTHOR David Kilzer =cut