SQL SERVER – How to Allow Only Alphabets in Column – Create Check Constraint to Insert Only Alphabets

To allow only alphabets in a SQL Server column, first define which letters are allowed. A reader asked for a database error when other characters are inserted. This example accepts only English letters A-Z and a-z. It rejects digits, spaces, punctuation, empty strings, and NULL.

Round wooden pieces fit a blue sorting frame while an angular red piece remains outside.

Create the constraint and test an insert

Run this complete example in a new SSMS query window. It uses a local temporary table and removes that table afterward. No existing application table is changed.

CREATE TABLE #LetterValues
(
    ValueID int NOT NULL,
    LetterText nvarchar(100) NOT NULL,
    CHECK
    (
        DATALENGTH(LetterText) > 0
        AND LetterText COLLATE Latin1_General_100_BIN2
            NOT LIKE N'%[^A-Za-z]%'
    )
);
INSERT INTO #LetterValues (ValueID, LetterText)
VALUES (1, N'SQLAuthority'), (2, N'ABC'), (3, N'abc');
BEGIN TRY
    INSERT INTO #LetterValues (ValueID, LetterText)
    VALUES (4, N'SQLAuthority 1');
END TRY
BEGIN CATCH
    SELECT ERROR_NUMBER() AS ErrorNumber,
           ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
SELECT ValueID, LetterText
FROM #LetterValues
ORDER BY ValueID;
DROP TABLE #LetterValues;

The first three values are inserted. The attempt to insert SQLAuthority 1 raises error 547, which the demo catches and displays. The final result contains only the three valid rows.

The TRY...CATCH block lets the demonstration continue after the expected error. Your application should handle a rejected write and report it clearly. Do not silently treat that failure as a successful insert.

Why the constraint has three parts

PartWhat it does
NOT NULLRejects a missing value.
DATALENGTH(LetterText) > 0Rejects an empty string.
NOT LIKE N'%[^A-Za-z]%' with BIN2 collationRejects any character outside the two allowed letter ranges.

Inside the brackets, ^ means a character outside the listed ranges. The surrounding percent signs allow that character to occur anywhere in the value. NOT LIKE requires that no such character exists.

An empty string contains no forbidden character, so the pattern alone accepts it. Also, a CHECK rejects FALSE, but an unknown result from NULL can pass. That is why the example handles empty strings and missing values separately.

The binary Latin1_General_100_BIN2 comparison makes the allowed ranges explicit. The original [A-Z] example depended on the column collation. Linguistic sorting rules can include characters outside the English alphabet, and case sensitivity changes lowercase handling.

This COLLATE applies to the constraint expression. It does not change the database collation or the column’s normal sorting behavior. Both uppercase and lowercase ranges are listed deliberately.

Contains a letter is different from contains only letters

LIKE N'%[A-Za-z]%' asks whether at least one letter exists. It accepts ABC123 and ABC!. The column needs the opposite test: reject any character that is not an allowed letter.

SELECT v.Sample,
       CASE WHEN v.Sample COLLATE Latin1_General_100_BIN2
                 LIKE N'%[A-Za-z]%'
            THEN 'Yes' ELSE 'No' END AS ContainsALetter,
       CASE WHEN DATALENGTH(v.Sample) > 0
                 AND v.Sample COLLATE Latin1_General_100_BIN2
                     NOT LIKE N'%[^A-Za-z]%'
            THEN 'Yes' ELSE 'No' END AS OnlyLetters
FROM (VALUES (N'ABC'), (N'ABC123'), (N'ABC!'), (N'123')) AS v(Sample);
SSMS comparison of Sample, ContainsALetter and OnlyLetters: ABC passes both, ABC123 and ABC! contain letters but fail OnlyLetters, and 123 fails both.
The positive pattern finds one letter. The negative-character pattern checks the entire value.

Rejecting only digits is also insufficient. NOT LIKE N'%[0-9]%' still allows punctuation and other unwanted characters. Define the allowed set instead of trying to list every forbidden character.

Why use nvarchar and the N prefix?

The example keeps incoming Unicode characters intact until the constraint evaluates them. An accented letter is then rejected by the stated ASCII-only rule. A conversion into a non-Unicode type before validation can change the input you intended to check.

Keep the N prefix on the pattern and string literals. With this nvarchar comparison, a trailing space is significant and is rejected. Test leading spaces, trailing spaces, and tabs separately instead of treating them as one case.

This rule is suitable only when the business requirement is that narrow. Personal names can contain accents, spaces, apostrophes, hyphens, and letters from other writing systems. I would not use this constraint as a general name validator.

Add the rule to an existing table

Inspect existing values before adding a constraint. This runnable example uses a temporary table with two valid rows. The first query returns any values that would violate the new rule.

CREATE TABLE #ExistingLetterValues
(
    ValueID int NOT NULL,
    LetterText nvarchar(100) NULL
);
INSERT INTO #ExistingLetterValues (ValueID, LetterText)
VALUES (1, N'Alpha'), (2, N'Beta');
SELECT ValueID, LetterText
FROM #ExistingLetterValues
WHERE LetterText IS NULL
   OR DATALENGTH(LetterText) = 0
   OR LetterText COLLATE Latin1_General_100_BIN2
      LIKE N'%[^A-Za-z]%';
ALTER TABLE #ExistingLetterValues WITH CHECK
ADD CHECK
(
    LetterText IS NOT NULL
    AND DATALENGTH(LetterText) > 0
    AND LetterText COLLATE Latin1_General_100_BIN2
        NOT LIKE N'%[^A-Za-z]%'
);
SELECT ValueID, LetterText
FROM #ExistingLetterValues
ORDER BY ValueID;
DROP TABLE #ExistingLetterValues;

In this example, the inspection returns no rows and the constraint is added successfully. For your own table, adapt the inspection query and ALTER TABLE statement. The temporary-table creation, sample inserts, and cleanup belong only to the demonstration.

The existing column is nullable, so this constraint includes LetterText IS NOT NULL explicitly. Its metadata remains nullable, but the enabled constraint rejects null values. For a new table, declaring the column NOT NULL makes that requirement clearer.

WITH CHECK validates the rows already stored. If the inspection finds invalid values, review and correct them before adding the constraint. Do not use WITH NOCHECK to hide the existing violations.

Adding and validating a constraint on a large table requires planned deployment time. It can scan data and take locks. Test that operation before applying it to a busy production table.

Test more than one rejected value

The same rule applies to updates of this column. I tested accepted letters, invalid inserts, a rejected update, and validation of existing rows. The update failed with error 547 and left the original value unchanged.

SSMS TestCase, Outcome and ErrorNumber results: uppercase, lowercase and mixed case accepted; digits, spaces, empty string, accent and hyphen rejected with 547; NULL rejected with 515.
Ten selected input tests. Error 547 comes from the CHECK constraint; error 515 comes from NOT NULL.

Additional tests rejected an apostrophe, a tab, a NUL character, a nonbreaking space, a fullwidth letter, and a combining accent. These results were measured on SQL Server 2025. Keep the same cases when testing your own version and data flow.

Run all 16 input tests
SET NOCOUNT ON;
CREATE TABLE #AcceptedLetters
(
    LetterText nvarchar(100) NOT NULL,
    CHECK (DATALENGTH(LetterText) > 0
       AND LetterText COLLATE Latin1_General_100_BIN2
           NOT LIKE N'%[^A-Za-z]%')
);
DECLARE @Cases TABLE
(
    CaseID int, TestCase varchar(30), Sample nvarchar(100), Expected varchar(8)
);
INSERT INTO @Cases
VALUES (1, 'Uppercase', N'ABC', 'Accepted'),
       (2, 'Lowercase', N'abc', 'Accepted'),
       (3, 'Mixed case', N'SQLAuthority', 'Accepted'),
       (4, 'Contains digits', N'ABC123', 'Rejected'),
       (5, 'Internal space', N'SQL Authority', 'Rejected'),
       (6, 'Trailing space', N'ABC ', 'Rejected'),
       (7, 'Empty string', N'', 'Rejected'),
       (8, 'NULL', NULL, 'Rejected'),
       (9, 'Accented letter', N'Jos'+NCHAR(233), 'Rejected'),
       (10, 'Hyphen', N'ABC-DEF', 'Rejected'),
       (11, 'Apostrophe', N'O''Neil', 'Rejected'),
       (12, 'Tab', N'A'+NCHAR(9), 'Rejected'),
       (13, 'NUL character', N'A'+NCHAR(0)+N'B', 'Rejected'),
       (14, 'Nonbreaking space', N'A'+NCHAR(160), 'Rejected'),
       (15, 'Fullwidth letter', NCHAR(65313), 'Rejected'),
       (16, 'Combining accent', N'e'+NCHAR(769), 'Rejected');
DECLARE @Results TABLE
(
    CaseID int, TestCase varchar(30), Expected varchar(8), Outcome varchar(8), ErrorNumber int
);
DECLARE @CaseID int = 1, @Sample nvarchar(100), @TestCase varchar(30), @Expected varchar(8);
WHILE @CaseID <= 16
BEGIN
    SELECT @Sample = Sample, @TestCase = TestCase, @Expected = Expected
    FROM @Cases WHERE CaseID = @CaseID;
    BEGIN TRY
        INSERT INTO #AcceptedLetters (LetterText) VALUES (@Sample);
        INSERT INTO @Results VALUES (@CaseID, @TestCase, @Expected, 'Accepted', NULL);
    END TRY
    BEGIN CATCH
        INSERT INTO @Results VALUES (@CaseID, @TestCase, @Expected, 'Rejected', ERROR_NUMBER());
    END CATCH;
    SET @CaseID += 1;
END;
SELECT TestCase, Expected, Outcome, ErrorNumber
FROM @Results ORDER BY CaseID;
DROP TABLE #AcceptedLetters;

Client-side validation can give an immediate, friendly message. The database constraint protects ordinary writes from other applications and scripts too. Keep both rules consistent, and do not disable the constraint during normal writes.

Define the allowed characters, handle empty and missing values, and test the exact input your database receives.

Published by Pinal Dave on SQLAuthority. More of my work at pinaldave.com.


Discover more from SQL Authority with Pinal Dave

Subscribe to get the latest posts sent to your email.

SQL Constraint and Keys, SQL Scripts, SQL Server
Previous Post
Scheduling an Agent Job for Weekday Office Hours Only
Next Post
SQL SERVER – Working with Business Days in SQL Server – A Different Approach

Related Posts

11 Comments. Leave new

  • Pinal, this solution is deceptively simple, can you explain why “WHERE FirstCol LIKE ‘%[A-Z]%’ ” is not the correct solution

    Reply
    • CREATE TABLE TestTable
      (ID INT, FirstCol VARCHAR(100),
      CONSTRAINT FirstCol CHECK (FirstCol NOT LIKE ‘%’ +’[^A-Z]‘+’%’))
      GO
      – This will be successful
      INSERT INTO TestTable (ID, FirstCol)
      VALUES (1, ‘SQLAuthority’)
      GO
      – This will throw an error
      INSERT INTO TestTable (ID, FirstCol)
      VALUES (1, ‘SQLAuthority 1′)
      GO
      – Clean up
      DROP TABLE TestTable
      GO

      Reply
  • Hi,
    Normally i validate such thing in front end,or before insert in proc.
    Suppose I create such constraint then what will be its impact in performance.Like I use that table in select as column or i use that column in where condition.

    Thanks

    Reply
    • I do agree with you Kumar Harsh. These sort of validations would be better to be handled in front end. But what if someone updates or insert the records directly on the database? In some cases, it is not avoidable to have a constraint like this.

      Reply
  • Hi,Andrew G
    WHERE FirstCol LIKE ‘%[A-Z]%’ will look for existence of alphabets, but it will not check if there is any non-alphabets

    example

    select col from
    (
    select ‘AG12’ as col union all select ‘test’
    ) as t
    WHERE col LIKE ‘%[A-Z]%’

    Reply
  • “WHERE FirstCol NOT LIKE ‘%[0-9]%’ ”

    :)

    Reply
  • Hi,

    This accepts only Alphabets in Column

    USE tempdb
    GO
    — Create Test table
    CREATE TABLE TestTable
    (ID INT, FirstCol VARCHAR(100),
    CONSTRAINT FirstCol CHECK (FirstCol LIKE ‘[A-Z]’))
    GO
    — This will be successful
    INSERT INTO TestTable (ID, FirstCol)
    VALUES (1, ‘S’)
    GO
    — This will throw an error
    INSERT INTO TestTable (ID, FirstCol)
    VALUES (1, ‘SQLAuthority’)
    GO
    — This will throw an error
    INSERT INTO TestTable (ID, FirstCol)
    VALUES (1, ‘1’)
    GO
    — Clean up
    DROP TABLE TestTable
    GO

    Reply
  • if i don’t want none english letter such as : Ònchann, how to protect?

    Reply
  • Tayyaba Farhat
    June 10, 2017 4:36 am

    can you please elaborate how not like is working with \%[^a-z]%’

    Reply
    • Muhammad Abubakar Riaz
      April 17, 2019 12:31 pm

      This is due your “collation” settings that dictates that small and capital abc should be assumed same character.

      Reply
  • webdesignvietnam
    December 10, 2019 7:40 am

    ALTER TABLE table_users
    ADD CONSTRAINT username_char_integer
    CHECK(username LIKE ‘%[^a-zA-Z0-9]%’);
    — CHECK(username LIKE ‘^[^a-zA-Z0-9]*$’);

    I am add constraint for table_users[username] but not work. I still insert abc%#$$ .. Could you help, How do I add ?

    Regards

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.