mssql
Skill1 starsChanged 13 days agoMITView on GitHub
Use when connecting to, querying, or troubleshooting a SQL Server database, running ad hoc T-SQL, or writing SQL Server migration, seed or schema scripts. Trigger words - sqlcmd, bcp, Msg 264, row goal, slow OFFSET FETCH, IDENTITY rebuild, schema.sql, seed.sql, trigger OUTPUT clause.
- Deletes or force-pushes
1 other project uses a version of this.
Adopted by
Most recently taken up by
- sanjay3290/ai-skillstheir own version, first seen Jul 6, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- sanjay3290/ai-skills★ 452same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository30 other files it gives its agents.
- angular-crud-gotchasSkill
- aws-lightsail-container-deploySkill
- bannerlord-decompileSkill
- codegen-t4-templatesSkill
- csharpSkill
- delphi-code-smellsSkill
- delphi-firedacSkill
- delphiSkill
- delphi-types-and-unitsSkill
- difftasticSkill
- dockerSkill
- efcore-aspnet-reviewSkill
- git-bash-editingSkill
- github-issue-creatorSkill
- microsoft-docsSkill
- minimal-comments-and-docsSkill
- msbuildSkill
- mstest-assertionsSkill
- mysqlSkill
- nginx-config-testingSkill
- odata-generated-gridsSkill
- postgresSkill
- powershellSkill
- react-crud-gotchasSkill
- sanitize-for-open-sourceSkill
- self-contained-deploymentSkill
- skill-writerSkill
- ui-conventionsSkill
- verify-in-running-appSkill
- winui3Skill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 11
Single statement only: Never send several statements separated by .
- Distinctive: line 14
Credentials: Never echo a full connection string or password.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
MS SQL Server
Safety rules (apply whenever running SQL against SQL Server)
- Idempotent where possible. No
CREATE TABLE IF NOT EXISTS: guard DDL withIF OBJECT_ID('dbo.TableName', 'U') IS NULL. For seed data useMERGEorIF NOT EXISTS (SELECT 1 FROM ... WHERE ...) INSERT ..., not a plainINSERT. - Single statement only. Never send several statements separated by
;(or on separate lines with noGO) in one execution: it protects against an accidental or injected stacked statement. - Timeouts. 10 s connection timeout (
Connection Timeout=10). 30 s query timeout client-side (SqlCommand.CommandTimeout = 30/ EF Core's command timeout): SQL Server has no server-side per-statement cap like MySQL'sMAX_EXECUTION_TIME.SET LOCK_TIMEOUT 30000;bounds how long a statement waits on a blocked resource. - Row cap. Ad hoc inspection SELECTs use
SELECT TOP 10000 ...(orOFFSET 0 ROWS FETCH NEXT 10000 ROWS ONLYwith anORDER BY). - Credentials. Never echo a full connection string or password; redact before showing any command or error output.
Tool: python C:/Github/tools/sql_run.py --engine mssql --host <server> --trusted|--user <login> --db <db> -e "<one statement>" enforces rules 2 to 5 (refuses a second statement and GO, 10 s / 30 s timeouts, 10000 row stop, password only via SQLCMDPASSWORD, redacted output) and notes a non-idempotent statement. Read its docstring for the flags (--read-only, --via <container>, --dry-run).
Design and EF Core notes
- Windows Integrated Auth does not work once the workload may run in a container or the cloud. If that is possible, design for username/password auth from the start.
- The
mcr.microsoft.com/mssql/serverimage is Linux-based. Retagging it for a registry push is in thedockerskill. DATETIME2(0)instead ofDATETIMEOFFSETis reasonable when the application normalizes everything to UTC itself.
| Wrong | Right | Why |
COUNT(*) to get a row count | Query sys.partitions. Through EF Core use SqlQueryRaw<int?> and alias the column as Value | A table scan; the scalar mapping only picks up a column called Value |
The same column twice in one UPDATE ... SET, from two independent IFs that can both fire | At most one assignment per column: IF <force-condition> SET col = <forced> ELSE IF <caller supplied a value> SET col = <caller's value> | Msg 264: "specified more than once in the SET clause". There is no "last write wins" |
Exporting data and schema
| Wrong | Right | Why |
sqlcmd ... -E -U <login> (both on the command line) | Pass -E or -U/-P, not both | Sqlcmd: The -E and the -U/-P options are mutually exclusive. Same message from the ODBC sqlcmd 16.0.1000.6 and go-sqlcmd 1.10.0. SQLCMDUSER/SQLCMDPASSWORD set in the environment did not trigger it with either: -E still used the Windows login |
sqlcmd -E -i C:/Users/me/x.sql (a forward-slash absolute path) | A relative path (-i x.sql) or backslashes (-i 'C:\Users\me\x.sql') | The ODBC sqlcmd 16.0.1000.6 reads the path as C: plus switches: /Users becomes -U, so you get the same misleading message "The -E and the -U/-P options are mutually exclusive"; C:/Specs/x.sql gave "Error occurred while opening or operating on file C: (Reason: Access is denied)". Relative and backslash paths worked from Git Bash and from PowerShell |
sqlcmd to export long generated text | bcp "SELECT ..." queryout file.txt -c -T -S server -d db -r '\n' | sqlcmd cuts varchar(max) and other max-width columns at 256 characters by default (a plain varchar(8000) printed in full). -y 0 removes the cut but is refused with -h; with -h -1 use -y 8000. bcp has no width limit (an 8000-character value came out whole); rows with embedded newlines span lines (4 rows with an embedded LF and CRLF came out as 6 lines, and on Windows -r '\n' writes the row end as CRLF, bytes 0d0a). To keep rows intact use terminators that cannot occur in the data, for example -t '~|~' -r '~#~'; the file split cleanly on ~#~ and bcp in with the same terminators loaded all 4 rows back with their newlines |
- To copy a schema to another database, dump
sys.tables/columns/types/default_constraints,sys.foreign_keys(+_columns)andsys.indexes(+_columns)withsqlcmd -W -h -1 -s "|"into small files and generate the other DDL from them; generateINSERTs with aSELECTthat builds the literals (REPLACE(x, '''', ''''''),CONVERT(varchar(23), d, 121),CASE bit WHEN 1 ...) and run it throughbcp. - Output for generated text:
-y 0(alone, never with-h) prints no header line; trim trailing spaces per line and add-f 65001for UTF-8. Prove a schema/seed script pair by creating an empty database, running both twice, regenerating the schema from the result and diffing it against the original. A view or procedure created withCREATE OR ALTERis stored with the wordsOR ALTERblanked to spaces, so the regenerated text differs from the first only by spaces and a trailing blank line: normalise whitespace before the diff (tables, keys, indexes, defaults, checks and foreign keys came back identical). - Backup/restore for a scratch copy:
BACKUP DATABASE X TO DISK = N'<path>' WITH COPY_ONLY, INIT(copy-only so the real backup chain is untouched), thenRESTORE DATABASE X_scratch FROM DISK = ... WITH MOVE '<logical data name>' TO '<new .mdf>', MOVE '<logical log name>' TO '<new .ldf>'. The service account writes the file, so useSERVERPROPERTY('InstanceDefaultBackupPath')(andInstanceDefaultDataPathfor the new files), not a user temp folder, and get the logical names fromRESTORE FILELISTONLY.sqlcmd -bplus$LASTEXITCODEis how a PowerShell script learns of a failure (a failing native command does not stop the script). Drop the copy withALTER DATABASE X_scratch SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE X_scratch;, listsys.databasesafterwards, and delete the.bakfrom the backup folder (a plainrmfrom the shell worked); never enablexp_cmdshellfor this. Checked withInvoiceSystem(23 tables in the copy, as in the original).
Scripts written from the catalog
- CHECK constraints:
sys.check_constraintsjoined tosys.columnsonparent_object_id/parent_column_id. A table-level check mentioning one column hasparent_column_id = 0: find the column by reading the definition.IN ('a','b')is stored as an OR chain in the catalog's own order (([s]='Closed' OR [s]='On hold' OR [s]='Open')). Skipis_disabled = 1. - A key sequence table (
GetNextID) must lock the whole table (WITH (TABLOCKX)) inside its transaction, so every insert of every listed table queues behind one counter; say so next to the script. Seed each counter fromMAX(key). - Triggers that call a linked server run inside the writing statement: an unreachable target (
Could not find server) rolls back the user's write.UPDATE(col)is true when the column is in the SET list even if the value did not change. text, ntext and image columns cannot be read frominserted. - A bulk change across tables needs no run-time metadata walk when the script is generated: write the plain
UPDATEper table and column. - History by trigger or by the engine: an
AFTER UPDATE, DELETEtrigger readsdeleted(the before-image);EXISTS (SELECT 1 FROM inserted)tells update from delete. UseSYSUTCDATETIME()andSUSER_SNAME()(the login: a service account when the app shares one). A system-versioned table (PERIOD FOR SYSTEM_TIME,SYSTEM_VERSIONING = ON (HISTORY_TABLE = ...)) needs a primary key, keeps the history itself and records no user; refuse a trigger-based trail on it. History tables carry no key, default or foreign key from the source, andnvarchar(max)must be declaredmax, not(0).
| Wrong | Right | Why |
| Making a column IDENTITY with an in-place change | Rebuild in one transaction with SET XACT_ABORT ON: sp_rename the table to _old, drop the foreign keys that point at it (and the child's FK to it) first, CREATE TABLE the new one with IDENTITY(1,1) and a primary key with a different name from the old one (the old key keeps its name after sp_rename; the same name fails with Msg 2714), SET IDENTITY_INSERT ... ON, INSERT ... SELECT with an explicit column list (ids kept), OFF, DROP TABLE _old, then recreate defaults, indexes and foreign keys WITH CHECK. Create named defaults and FKs after the old table is dropped. Make it re-runnable by testing COLUMNPROPERTY(OBJECT_ID('dbo.T'), 'Col', 'IsIdentity'); afterwards check sys.foreign_keys.is_not_trusted is 0 everywhere. Rename a column with sp_rename 'dbo.T.Old', 'New', 'COLUMN' (it prints a harmless "Caution") | A column cannot be made IDENTITY in place. Default, FK and PK names are schema-wide |
EXEC sp_executesql N'..' + @x + N'..' | Build the statement in an nvarchar(max) variable first | It is a syntax error |
STRING_AGG with a separator such as N',' + @nl | A literal or a variable | The separator must be one of those |
| An aggregate mixing an outer-query column with inner columns | Use the inner c.object_id in IDENTITYPROPERTY | Msg 8124 |
| Quoted literals built with doubled quotes by hand | 'N' + CHAR(39) + REPLACE(col, CHAR(39), CHAR(39) + CHAR(39)) + CHAR(39) | Keeps the quoting readable and correct |
- Generating
schema.sqlandseed.sql: runC:\Github\tools\mssql_gen_scripts.py(see the README there) instead of rewriting a generator. Run the result withsqlcmd -I -f 65001(QUOTED_IDENTIFIERon, UTF-8 input), and sendmoneyandsmallmoneyout withCONVERT(nvarchar(50), col, 2)or the values are rounded. The catalog queries, the literal style for each column type, system-versioned tables, triggers and filtered indexes are in reference/schema-seed-generation.md: read it when the tool is not enough. - Unique name indexes that are not filtered (
IX_Unique_*Name) already cover a "unique among active rows" rule more strictly but also block reusing the name of an inactive row: say so before adding a filtered index.
Paged, searched and sorted lists through EF Core
| Wrong | Right | Why |
A selective search plus ORDER BY a joined column plus OFFSET/FETCH left as is | Run the SQL EF logged with SET STATISTICS TIME ON, then with OPTION (USE HINT('DISABLE_OPTIMIZER_ROWGOAL')). Fix with a DbCommandInterceptor that appends the hint to commands whose text starts with the tag from .TagWith("DisableRowGoal"); tag only queries that carry a search (a plain newest-first page needs the row goal). Measure before keeping it | It can take 4 to 17 s on 100,000 rows while each part alone takes under 100 ms: SQL Server assumes the first 10 matches come quickly (a row goal). Reproduced on TimeEntry_test (E_TimeSheet, 100,000 rows, joined to Employee, ordered by the employee name, page 1): a text filter that matches nothing OR-ed with a list of 3 employee ids took 17,979 ms with the default plan and 26 ms with the hint, while the text filter alone took 85 ms and the joined sort alone 18 ms. It did not reproduce on two small synthetic schemas, so it depends on the data and the exact query |
list.Contains(x.Col) on a big list | EF.Constant(list).Contains(x.Col) for lists of a few hundred ids. Find those ids with a small first query instead of joining the big table inside the filter | In EF Core 9.0.16 it becomes IN (SELECT [i].[value] FROM OPENJSON(@__ids_0) ...), which gave that bad plan on TimeEntry_test: 18,058 ms against 31 to 49 ms with the hint, as sp_executesql statements with the exact EF text. EF Core 10.0.13 sends one parameter per element (IN (@ids1, @ids2, @ids3)) instead, and the same query ran in 110 ms (82 ms with the hint), so the problem is mostly an EF Core 9 one. The constant form inlines IN (1, 2, 3) in both |
| Saving a row through EF Core on a table with an enabled trigger | Disable the trigger, or tell EF not to use OUTPUT | EF's default OUTPUT clause fails (The target table ... cannot have any enabled triggers if the statement contains an OUTPUT clause without INTO); the real database does the same, so a generated EF API cannot save such a table |
| A script with a view or trigger that is not first in its batch | GO before and after (sqlcmd reads it, ADO.NET does not) | A view or trigger must be first in its batch. sys.sql_modules.definition is the whole original CREATE text |
- To see the SQL EF sends, see "Seeing the SQL EF sends" in the
efcore-aspnet-reviewskill. - Building a page endpoint, a duplicate-row guard or a test provider swap is EF Core and ASP.NET work, not SQL Server work: see the
efcore-aspnet-reviewskill.
How this was verified
Tested on this machine. The evidence, the versions used and the items not re-run are in reference/verification.md: read it before saying a claim here was tested, and treat anything listed there as not re-run as unverified.
What this does not prove
- That a rule holds on another SQL Server version or edition, on Azure SQL, or in the Linux container image.
- That the row-goal hint or
EF.Constanthelps another query, table or data size: measure it first, as the table says. - That a script generated from the catalog is complete: routines, linked servers, non-
dboschemas and other collations were not all covered.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

