SQL Parameter Replacer
Processed Client SidePaste a parameterised SQL script and its parameter values, and get the final script back with every placeholder replaced by a correctly quoted literal — ready to paste into a client and run.
Bookmark this tool now — skip the search next time you need it.
About SQL Parameter Replacer
This tool runs entirely in your browser. Whatever you paste is processed on your own device and is never uploaded, logged, or sent to any server.
A parameterised query is not something you can run. The log line says `WHERE status = ? AND created_at >= ?`, the ORM prints `:status` and `:start_date`, and the values sit somewhere else entirely — so reproducing what the application actually executed means splicing them back in by hand, getting the quoting right, and hoping you did not miss one. This tool does that splice: paste the script in the top pane, the values in the bottom pane, and the right-hand pane holds a script you can paste straight into a client and run. It reads :name, @name, ?, $1, {{name}}, ${name}, #{name} and %(name)s, quotes each value the way your engine expects, and tells you about any placeholder you left unbound before you find out from an error.
Key features
- Nine placeholder styles recognised at once, or one pinned from the toolbar: :name, @name, ?, $1, {{name}}, ${name}, #{name}, %(name)s, %s, plus Oracle &name on request
- Placeholders inside string literals, quoted identifiers and comments are left untouched — a query containing the text ‘:status’ in a WHERE clause is not rewritten
- Values typed automatically: numbers stay bare, strings get quoted, true/false become TRUE/FALSE or 1/0 depending on the engine, and an empty value becomes NULL
- A JSON array binds to an IN list — ["US","GB"] becomes (‘US’, ‘GB’) so `IN :countries` works as written
- Backticks are the escape hatch: `CURRENT_TIMESTAMP` is injected as SQL rather than quoted as a string, which is how you bind an expression, a column, or a table name
- Quotes inside values are escaped for the dialect — O’Brien becomes ‘O’’Brien’, and a backslash is doubled for MySQL and left alone everywhere else
- Parameters accepted as a JSON object, a JSON array, or plain name = value lines with # and -- comments
- Positional styles bind in order of appearance, and numbered ones ($1, ?3, :2) bind by their own number even when they repeat
- Every substitution shown as a chip — placeholder, value, and how many times it appeared — with unbound ones flagged in red in both panes
- Unused parameters reported too, which is usually a typo in a name rather than a spare value
- "Fill from script" writes a JSON parameter set covering every placeholder, keeping the values already entered
- Dialect detected from the script, upload a .sql file, copy or download the result, and nothing is ever uploaded
How to use it
- Paste the parameterised script into the top-left pane, or upload a .sql file.
- Put the values in the bottom-left pane: one name = value per line, or a JSON object. Click "Fill from script" to have every placeholder listed for you.
- Leave Dialect on Auto detect, or pick one if the script has no dialect-specific syntax.
- Leave Placeholder style on Auto detect unless your script uses Oracle &name, or a style you want pinned so nothing else matches.
- Read the chips under the panes to confirm what each placeholder became, and look for anything marked red or reported as unused.
- Copy the final script or download it as .sql, then run it.
Tips & common mistakes
- Quoting is how you override the type guess. `id = 007` binds the number 7; `id = "007"` binds the string and keeps the zeros. Switch Values to "always quote" to do that for every parameter at once, which is what you want against CHAR key columns.
- Backticks bind SQL, not a value. `now = `CURRENT_TIMESTAMP`` produces `CURRENT_TIMESTAMP` unquoted; without them you would get the string ‘CURRENT_TIMESTAMP’, which is not a timestamp. The same trick binds a table name, a column, or a whole subquery.
- Write `IN :ids` rather than `IN (:ids)` and give ids a JSON array — the list literal brings its own parentheses. An empty array comes out as (NULL) with a warning, because IN () is a syntax error in every engine.
- Escaping is dialect-specific in exactly one place that bites: MySQL reads a backslash inside a literal as an escape by default, so a Windows path or a regex is doubled for MySQL and left alone for PostgreSQL, SQLite, SQL Server and Oracle. Set the dialect before you trust a value containing a backslash.
- The output is a script you are about to run, not a substitute for a prepared statement. Binding values in the driver is what stops SQL injection; this tool exists for the other job — reproducing, reviewing, or hand-running a query whose values you already have.
- A count that looks wrong is nearly always a style collision. `?` is also a PostgreSQL jsonb operator and `&` is bitwise AND, so pin the style in the toolbar when Auto detect claims placeholders your script does not have.
- Names are matched case-sensitively first. A parameter set exported as USER_ID still binds to :user_id, but the tool says it ignored case rather than doing it quietly — real drivers would not.
- Nothing inside a string literal or a comment is ever substituted, and the status row counts what it skipped. If a placeholder you expected went unbound, check it is not sitting inside quotes.
- Oracle &name is off unless you select it, because & is bitwise AND elsewhere and `flags&mask` would read as a substitution variable. SQL*Plus substitution is textual, so "never quote" or a backtick value usually matches what it means.