sethserver.com
A red and silver server tower with a vault door on its front panel, the dial marked with uppercase, lowercase, digit and symbol segments, lit dramatically on a dark navy background.

SQL Server Password Generator (Meets CHECK_POLICY)

By Seth Black • Updated: September 17, 2026

generating...

Create a login and database user

Run as a sysadmin (or a login with ALTER ANY LOGIN and rights in the database). The password is already escaped for T-SQL.

Change an existing login's password

Connection strings (password escaped)

First line: ADO.NET / Microsoft.Data.SqlClient. Second line: ODBC Driver 18.

sa password for the Docker image

A separate password for sa, because the app login and sa should never share one. Same policy guarantees.

generating...

Env file line (docker run --env-file sql.env)

Docker reads env files literally, so nothing needs escaping here.

docker run (bash)

docker-compose.yml

Compose treats $ as the start of a variable, so each one is doubled.

Change the sa password later

Both passwords are generated in your browser with crypto.getRandomValues. Nothing is sent to my server or stored. Change the options and the T-SQL, connection strings and Docker settings rebuild themselves.

SQL Server has an unusual quirk for a password generator: it will flat-out refuse a password that doesn't meet its policy, and the SQL Server Docker container will refuse to start. So "random" isn't enough. This generator only hands you passwords that pass, and then does the escaping for the three or four places the password has to go.

The SQL Server password policy, exactly

SQL Server logins that use SQL Server authentication can use the Windows password policy mechanisms. CHECK_POLICY is ON by default in CREATE LOGIN. Microsoft Learn's "Password Policy" page lists the complexity rules as:

With CHECK_POLICY = ON, SQL Server also refuses passwords that are empty, the same as the computer or login name, or one of password, admin, administrator, sa and sysadmin. Passwords can be up to 128 characters.

Here's how the generator guarantees a pass. It won't let you enable fewer than three character groups. It rejects and redraws any password that doesn't contain at least one character from every group you enabled, that contains the login name (compared case-insensitively), that matches one of the banned words, or that contains $( (more on that below). Redrawing the whole password, instead of patching in a required character at a fixed spot, keeps every allowed password equally likely.

I tested the edges on SQL Server 2022 in Docker. A 7-character password with all four groups fails with Msg 33062 ("too short"). abcdefgh12, with only two groups, fails with Msg 33064 ("not complex enough"), and so does password. A password containing the login name fails with the same 33064 error even when the letter case differs. Abcdefgh12, with three groups and no symbol, passes. One more detail: a two-character login name inside the password was accepted, so the generator only checks login names of three or more characters. That matches how Windows treats short account names.

One thing the policy check doesn't cover: CHECK_EXPIRATION. It defaults to OFF in CREATE LOGIN. For a service account I leave it off and rotate on my own schedule, because an application login that expires at 3am is an outage, not a security control. The generated T-SQL says CHECK_EXPIRATION = OFF explicitly so the next person reading it knows it was a decision.

Single quotes, N'' and T-SQL escaping

In T-SQL a string literal is wrapped in single quotes, and a single quote inside it is written as two. The password It's becomes N'It''s'. The N prefix makes it a Unicode literal, which is harmless for ASCII and correct for everything else.

Microsoft's CREATE LOGIN page says passwords can't contain single quotes. In my test on SQL Server 2022, a login created with a doubled quote worked, and sqlcmd logged in with the raw password. It's still off by default here, because the places that break are the ones you don't control: deployment scripts that paste strings into SQL, config templating, and the occasional ORM migration. If you turn it on, the generated statements double every quote for you.

Double quotes and backslashes are never used. They cause more trouble in shells and connection strings than the entropy is worth.

Where the password goes

The generated script creates a server-level login and then a database user mapped to it, with db_datareader and db_datawriter. That's the usual application setup: it can read and write tables but can't change schema, create logins, or read other databases. If the app only reads, drop the writer role. Schema changes belong to a separate migration login. I wrote more about why in the principle of least privilege in the AI age.

If you paste the script into sqlcmd, or SSMS in SQLCMD mode, watch for $(. sqlcmd treats $(name) as a scripting variable anywhere in the script, including inside string literals. In my test, N'ab$(x)cd' printed "'x' scripting variable not defined" (and with -b the script exited with an error), and when a variable named x did exist, sqlcmd quietly replaced it and the string became abZZcd. That second case is the nasty one: you set a password that isn't the one you saved. The generator never produces $(. If you have an existing password that contains it, run sqlcmd with -x to turn off variable substitution.

Connection strings: semicolons, quotes and braces

A password with a ; in it splits a connection string in the wrong place. The two common formats escape differently:

FormatRule
ADO.NET (SqlClient)A value containing ;, ' or " must be wrapped in double quotes. If it contains " but no ', wrap it in single quotes instead. A quote character that matches the wrapper is doubled.
ODBC Driver 18Wrap the value in braces: PWD={...}. A } inside the value is written as }}.

The ADO.NET rule is from the SqlConnection.ConnectionString documentation, and the generator follows the same logic as SqlConnectionStringBuilder. The ODBC docs say that values in braces are passed to the driver intact, and older Native Client docs say a braced value can't contain a closing brace at all, so I tested the doubled }} form against SQL Server 2022 with pyodbc and ODBC Driver 18 before putting it on this page. It worked.

Honestly, the best escaping is the escaping you don't write. In .NET, build connection strings with SqlConnectionStringBuilder. In Python with pyodbc, keep the password out of the string you format by hand, or at least wrap it in braces as shown.

SQL authentication vs Windows and Entra authentication

Everything above is about SQL Server authentication: a login name and password that SQL Server checks itself. Microsoft's guidance is blunt: "When possible, use Windows authentication." On Azure SQL the modern answer is Microsoft Entra ID with managed identities, where there's no password in your app at all. If your app runs on Azure, look there first.

SQL logins are still everywhere: Linux containers, apps outside the domain, vendor software, local development. On a Windows install, SQL logins only work if the server is in mixed mode ("SQL Server and Windows Authentication mode"); Windows Authentication mode turns SQL Server authentication off. Microsoft's docs also note that Azure SQL Database enforces password complexity.

Contained database users

A contained database user has its own password stored in the database, with no server login behind it, so the user moves with the database instead of having to be recreated on each server. On SQL Server you have to allow it first:

EXEC sp_configure 'contained database authentication', 1;
RECONFIGURE;
ALTER DATABASE [AppDb] SET CONTAINMENT = PARTIAL;
GO
USE [AppDb];
CREATE USER [app_user] WITH PASSWORD = N'PASTE-GENERATED-PASSWORD';
ALTER ROLE db_datareader ADD MEMBER [app_user];
ALTER ROLE db_datawriter ADD MEMBER [app_user];

The same password policy applies to contained users with passwords (I checked: abcdefgh12 gets the same Msg 33064). The connection string must name the database (Database=AppDb), because the user doesn't exist anywhere else. I ran this on SQL Server 2022 and logged in with sqlcmd using -d AppDb.

The sa login and the Docker image

The Linux image reads the sa password from MSSQL_SA_PASSWORD (SA_PASSWORD is deprecated). Microsoft's quickstart says it must follow the password policy, and if it doesn't, the container can't set up SQL Server and stops. I confirmed that the unhelpful way: with a weak password the container exited a few seconds after starting, and docker logs said "ERROR: Unable to set system administrator password: Password validation failed."

Quoting is the other trap. In bash, double quotes still expand $, so -e "MSSQL_SA_PASSWORD=Pa$$w0rd..." silently sets a different password from the one you think you set. The generated docker run uses single quotes (with any ' written as '\''). The env file is simpler: Docker reads each line literally. In a compose file, $ starts variable interpolation, so it has to be written $$, which the generated snippet does.

Microsoft also notes that MSSQL_SA_PASSWORD is visible in ps output and in the container's environment, so change the sa password after first start. The generated ALTER LOGIN [sa] handles that.

Better still, stop using sa. Microsoft's guidance is to create a new login in the sysadmin role, connect with it, and disable sa:

CREATE LOGIN [dba_seth] WITH PASSWORD = N'PASTE-ANOTHER-GENERATED-PASSWORD', CHECK_POLICY = ON;
ALTER SERVER ROLE sysadmin ADD MEMBER [dba_seth];
GO
-- reconnect as dba_seth, then:
ALTER LOGIN [sa] DISABLE;
ALTER LOGIN [sa] WITH NAME = [not_sa_anymore];

Renaming sa doesn't make it safe on its own, but it does make every script that blindly guesses "sa" fail before it gets to guessing passwords.

Generate a SQL Server password offline

These use the operating system's CSPRNG. Base64 output contains uppercase, lowercase and digits, so at this length it passes the complexity rule in practice, but it can in rare cases miss a group, so check it (or just use the generator above).

# PowerShell 7+
[Convert]::ToBase64String([Security.Cryptography.RandomNumberGenerator]::GetBytes(32))

# openssl
openssl rand -base64 32

# Python
python3 -c "import secrets; print(secrets.token_urlsafe(32))"

Common mistakes

A strong password is the easy part of database security. My book Databases in the Era of AI argues that secrets are the easy 10% and insecure data flow is the rest, and that's where most of the real damage happens.

SQL Server password FAQ

What are the SQL Server password requirements?

When CHECK_POLICY is ON, which is the default for CREATE LOGIN, SQL Server applies the Windows password policy. Under the complexity policy the password must be at least 8 characters, must not contain the login name, and must use characters from at least three of four groups: uppercase letters, lowercase letters, digits, and non-alphanumeric characters. It also rejects empty passwords and the words password, admin, administrator, sa and sysadmin. SQL Server passwords can be up to 128 characters.

How do I put a single quote in a SQL Server password?

Inside a T-SQL string literal a single quote is written as two single quotes, so the password It's becomes N'It''s'. The CREATE LOGIN documentation says passwords cannot contain single quotes, although in my test on SQL Server 2022 a doubled quote worked. Tools and scripts that build SQL by pasting strings together are exactly where it breaks, which is why this generator leaves single quotes out unless you turn them on.

What does MSSQL_SA_PASSWORD need for the SQL Server Docker image?

Microsoft says the MSSQL_SA_PASSWORD value must meet the SQL Server password policy: at least eight characters with characters from three of the four sets of uppercase letters, lowercase letters, digits and symbols. If it does not, the container cannot set up SQL Server and stops, and docker logs shows why. The older SA_PASSWORD variable is deprecated.

How do I escape a password in a SQL Server connection string?

For ADO.NET (SqlClient), a value that contains a semicolon, single quote or double quote must be wrapped in quotes. Wrap it in double quotes, and if it contains double quotes but no single quotes, single quotes work instead. For ODBC, wrap the value in braces, as in PWD={...}. Microsoft ODBC Driver 18 accepts a closing brace inside the value when it is doubled. The simplest fix is a connection string builder class, which does the escaping for you.

Should I disable the sa login?

Yes, once you have another sysadmin login you can use. Microsoft recommends creating a new login in the sysadmin role and then disabling sa. ALTER LOGIN sa DISABLE turns it off and ALTER LOGIN sa WITH NAME renames it, which stops attacks that assume the name sa. Your applications should never connect as sa in the first place.

Is this SQL Server password generator safe?

The passwords are generated in your browser with crypto.getRandomValues and never leave the page. Nothing is sent to my server or stored. If policy requires generating production credentials on your own machines, the PowerShell and openssl commands on this page do the same job offline.

Related tools: MongoDB Password Generator, Redis Password Generator, MySQL Password Generator, PostgreSQL Password Generator, and the general strong password generator.

-Sethers

Newsletter

One email, once a week.

Notes on databases, systems, and the occasional strong opinion about Python. No spam, unsubscribe anytime.

More to read

All tools →

My Password Generators Had 53 Bits of Entropy

Sep 21, 2026

API Key Generator with Prefix, Checksum and SHA-256

Sep 17, 2026

Bcrypt Generator: Hash and Verify Passwords in Your Browser

Sep 17, 2026