Try something like this:
WITH AreaCode (A) AS (
UNION ALL SELECT '([0-9][0-9][0-9])-'
), Prefix (P) AS (
), Last4 (L) AS (
), Ext1 (E1) AS (
SELECT ' x'
UNION ALL SELECT ' Ext.'
UNION ALL SELECT ' ext'
), Ext2 (E2) AS (
UNION ALL SELECT '[0-9][0-9]'
UNION ALL SELECT '[0-9][0-9][0-9]'
UNION ALL SELECT '[0-9][0-9][0-9][0-9]'
), Extension (E) AS (
UNION ALL SELECT E1 + E2 FROM Ext1 CROSS JOIN Ext2
WHERE NOT EXISTS (
CROSS JOIN Prefix
CROSS JOIN Last4
CROSS JOIN Extension
Y.PhoneNumber LIKE AreaCode + Prefix + Last4 + Extension
If you find patterns that are valid but not covered by the query, add them to the parts and pieces shown. If you find something that needs to be together in the two parts, then model it after the Extension CTE (which is either missing or a combination of Ext1 and Ext2). If you need to support international numbers, and they have different patterns (not matching the U.S. 3-3-4) then you'll need some analysis and proper correlating to make the right country codes match up with the right patterns. For example, I know that in certain parts of Brazil, this is a valid number: +55 85 1234-5678 (country code 55, area code two digits, then 4-4 pattern).
Another technique to help you analyze your data is this:
WITH Patterns (P) AS (
'1', '0'), '2', '0'), '3', '0'), '4', '0'),
'5', '0'), '6', '0'), '7', '0'), '8', '0'), '9', '0'
SELECT P, Count(*)
GROUP BY P;
This can help you understand what your data is like by ignoring the actual phone number differences between each row and paying attention only to the arrangement and count of digits. If there are a lot of alpha characters, try to start replacing valid patterns (such as "ext") with a value not found in the list, so you can collapse the rest of the spurious input into something that can be analyzed with a similar
Replace() for each letter in the alphabet.