Disable vi Autoindent Before Pasting SQL Scripts on Oracle Hosts
Disable vi Autoindent Before Pasting SQL Scripts on Oracle Hosts
Purpose
Pasting a SQL script copied from email, a Confluence page, or a ticket comment into a vi buffer over SSH — and watching every line shift one indent right of the previous one — is the most common and most frustrating vi failure mode an Oracle DBA encounters. The script that ran fine when executed directly from the wiki snippet now fails on the host with SP2-0042: unknown command " INSERT" on every line. The cause is autoindent: vi assumed each new line should match the indentation of the previous one, and the terminal cannot distinguish a real keypress from a pasted character, so the indent compounds.
Three vi options together prevent the cascade: :set noai (disable autoindent), :set nosm (disable showmatch — the bracket-bounce highlight that slows large pastes), and :set paste on vim-derived implementations (a single switch that turns off every paste-hostile feature at once). Set them before entering insert mode, paste the script, then restore the defaults so the next file edit retains expected behaviour.
The bug surfaces equally in classic vi on AIX/Solaris/HP-UX and in vim on Oracle Linux and RHEL, because both implement autoindent the same way. The fix is one of the first things to commit to muscle memory for any DBA who edits SQL scripts on remote Oracle hosts.
Code
1" In vi command mode, BEFORE pressing i to insert and pasting:
2:set noai
3:set nosm
4
5" On vim (Oracle Linux, RHEL, macOS) the single switch:
6:set paste
7
8" Now press i, paste the SQL, press Esc, then restore:
9:set ai
10:set sm
11:set nopaste
12
13" Optional — make the defaults paste-safe for all SQL files
14:autocmd BufRead,BufNewFile *.sql setlocal noai nosm
1# Persist for every interactive vi session — add to ~/.vimrc
2cat <<'EOF' >> ~/.vimrc
3" SQL-friendly defaults for the oracle user
4autocmd BufRead,BufNewFile *.sql setlocal noai nosm
5autocmd BufRead,BufNewFile *.pls setlocal noai nosm
6autocmd BufRead,BufNewFile *.pkb setlocal noai nosm
7EOF
Code Breakdown
:set noai
autoindent (abbreviated ai) makes vi copy the leading whitespace of the previous line onto each new line as you type. Useful for hand-editing structured code; catastrophic when the "typing" is actually a paste from the terminal, because every newline triggers another indent and the previous paste's indent is preserved on top of it. :set noai switches the behaviour off; :set ai switches it back on.
:set nosm
showmatch (abbreviated sm) briefly highlights the matching open-paren or open-brace when you type the closing one. During a paste of a multi-thousand-line SQL block with many balanced parentheses, the highlight redraws between every character and can slow the paste enough that the terminal buffer overflows and characters are dropped. :set nosm disables the highlight; the paste runs at terminal speed.
:set paste (vim only)
vim added a single paste mode in version 6 that disables every paste-hostile formatting feature at once: autoindent, smartindent, cindent, textwidth, formatoptions, expandtab, and abbreviation expansion. One switch on, one switch off. Classic vi (nvi, BSD vi, AT&T vi) does not have :set paste and requires the two individual noai/nosm toggles above.
autocmd BufRead,BufNewFile *.sql setlocal noai nosm
The persistent recipe. autocmd registers a callback fired whenever vim opens or creates a file matching the glob; setlocal scopes the option change to that buffer only so it does not leak into the next file edited in the same session. Three globs cover SQL*Plus scripts (*.sql), PL/SQL specifications (*.pls), and PL/SQL bodies (*.pkb).
Key Points
- The pasted indentation is real characters. Once the paste is in the buffer with cascading indent,
:set noaialone will not fix the existing damage — only the next paste. To repair the current buffer, use:%s/^ *//gto strip leading whitespace from every line, or paste again into a fresh buffer after togglingnoai. - Terminal emulator bracketed-paste mode helps modern setups. Recent iTerm2, GNOME Terminal, and PuTTY versions send "bracketed paste" escape sequences that vim 8+ detects and automatically enters
pastemode for. Thenoai/nosmrecipe is still the right default for older terminals and classic vi. expandtabis a separate fix for a different bug. If pasted code contains literal\ttabs and the destination requires spaces (Oracle PL/SQL style guides typically mandate spaces), use:set expandtaband:retabafter paste. This is independent of the autoindent problem.- SP2-0042 from SQL*Plus is the smoke alarm. When SQL*Plus prints
SP2-0042: unknown commandon every line of a pasted script, the script almost certainly has leading whitespace where SQL*Plus expects none. Re-open in vi withnoaiand re-paste from the source. viewis read-only vi and immune. If the only goal is to look at the pasted script without editing,view <file>opens read-only and avoids the entire autoindent/insert-mode question.
Insights and Best Practices
Build a SQL-safe .exrc or .vimrc for every Oracle host
The persistent fix belongs in the oracle user's ~/.exrc (classic vi) or ~/.vimrc (vim). A minimal SQL-safe profile:
1set noai
2set nosm
3set showmode
4set ruler
5set number
6set ts=4
7set sw=4
8autocmd BufRead,BufNewFile *.sql,*.pls,*.pkb,*.pks setlocal noai nosm
Source-control this alongside the rest of the DBA team's profile assets. Every new oracle user on every host gets the same paste-safe vi from day one.
Use a SQL*Plus heredoc when the script is short
For one-off paste-and-run that does not need to be saved to a file, skip vi entirely. Paste the SQL into a heredoc directly at the shell:
1sqlplus -s / as sysdba <<'EOF'
2SELECT tablespace_name, bytes/1024/1024 mb
3FROM dba_data_files
4ORDER BY 2 DESC;
5EOF
The 'EOF' quote disables shell variable expansion inside the heredoc, so a script with & substitution variables pastes verbatim. No vi, no autoindent, no SP2-0042.
Pair with dos2unix for cross-platform pastes
A SQL script copied from a Windows-authored ticket frequently arrives with \r\n line endings. SQL*Plus accepts them but Oracle's parser sometimes complains, and git diff always does. Run pasted scripts through dos2unix (or tr -d '\r' < file.sql > clean.sql) before commit.
Prefer :r !cat over hand-paste for very large scripts
For a multi-thousand-line paste, terminal buffer overflow becomes likely even with nosm. Stage the script as a temp file by scp (or vim - reading from stdin), then read it into the buffer:
1:r !cat /tmp/script.sql
Zero typing, zero autoindent risk, and the paste is one atomic operation rather than a stream of keystrokes.
When to Run This
- Before editing any SQL script copied from a wiki, email, or ticket comment over SSH
- When SQL*Plus emits
SP2-0042: unknown commandon every line of a freshly pasted script - When inheriting an Oracle host whose
.exrc/.vimrcis missing or unconfigured - During training of any DBA new to vi-on-remote-host workflows
- Whenever pasting into a terminal with bracketed-paste detection unavailable (legacy PuTTY, raw
telnet, IBM xterm)
Troubleshooting Common Issues
If :set noai does not stop the cascade, autoindent is being re-enabled by a filetype-detection plugin. Check :set ai? after the paste; if it returns autoindent, run :filetype off before pasting and :filetype on after.
If :set paste is rejected with "unknown option," the editor is classic vi rather than vim. Fall back to the two-option :set noai plus :set nosm recipe; both work on every vi-family editor.
If the paste appears truncated, the terminal buffer overflowed. Reduce paste size by splitting the script in halves, or use :r !cat <file> to read from a staged file rather than typing through the terminal.
If SP2-0042 persists after a clean noai paste, inspect the file with cat -A <file> (or od -c) to see hidden control characters and non-breaking spaces. Confluence and some email clients silently substitute non-breaking spaces (U+00A0) for ASCII spaces; SQL*Plus rejects them. Strip with sed -i 's/\xc2\xa0/ /g' <file>.
References
- Oracle Database SQL*Plus User's Guide and Reference 19c — SQL*Plus Error Messages (SP2-) — official reference for the
SP2-0042 unknown commandmessage that triggers the autoindent investigation - vim.org — :help 'paste' (Vim Reference Manual) — canonical vim documentation for
:set pasteand the relatedpastetoggleoption used in the persistent recipe - shutdownabort.com — Miscellaneous Useful UNIX (Wayback, 2013-01-15) — original source of the
:set noai nosmrecipe in the DBA Quick Guides corpus - oracle-base.com — Linux Articles — Tim Hall's Linux-for-Oracle-DBAs reference set, including SQL script management patterns on remote hosts
Posts in this series
- List Files Opened by an Oracle Process with lsof -p
- Delete the 500 Oldest Files in a Directory (Oracle DBA)
- Diagnose Oracle Net and RAC Interconnect Routing with netstat -r
- Unpacking Oracle Patch and Install Media with cpio
- Oracle Export Through a Named Pipe with mknod for Space-Constrained Hosts
- Recursive find and grep to Search Oracle Trace Files for Any String
- Find the Biggest Files First When an Oracle Filesystem Fills Up
- Scan Every Oracle Alert and Trace Log for ORA- Errors with grep
- vi Editor Commands Reference for Oracle DBAs
- Disable vi Autoindent Before Pasting SQL Scripts on Oracle Hosts
- Enable vi Command-Line Editing in ksh for Oracle DBA Shells
- Search UNIX Man Pages for Oracle DBA Tools with man -k