I have this personal opinion that one sign of a good DBA is their ability to automate things and, before the DBA world found PowerShell, the way to do this was with T-SQL.
For example, a T-SQL script to get permissions assigned to a database principal could also include a column to REVOKE
those permissions. This could be “automated” with some dynamic SQL.
SELECT dprin.name AS DatabasePrincipalName, OBJECT_NAME(dperm.major_id) AS ObjectName, dperm.permission_name AS PermissionName, N'REVOKE ' + dperm.permission_name + N' ON OBJECT::' + OBJECT_NAME(dperm.major_id) + N' FROM ' + dprin.name COLLATE Latin1_General_CI_AS AS RevokeMe FROM sys.database_permissions AS dperm INNER JOIN sys.database_principals AS dprin ON dperm.grantee_principal_id = dprin.principal_id WHERE dprin.name = 'public';

What about if we want to improve this?
This is nice but what about if we are paranoid forward-thinking enough to realize that this could cause us problems?
“How?” You ask. Well what happens if there existed another database, say [NeedsAllPermissions], with the same table name and the same login has permissions on it.
Are you going to revoke permissions from that database? It needs ALL of them! It says so in the name!
So in an effort to not shoot ourselves in the foot, we add in the database name to our revoke script.
SELECT dprin.name AS DatabasePrincipalName, OBJECT_NAME(dperm.major_id) AS ObjectName, dperm.permission_name AS PermissionName, N'USE ' + DB_NAME() + 'GO' + N'REVOKE ' + dperm.permission_name + N' ON OBJECT::' + OBJECT_NAME(dperm.major_id) + N' FROM ' + dprin.name COLLATE Latin1_General_CI_AS AS RevokeMe FROM sys.database_permissions AS dperm INNER JOIN sys.database_principals AS dprin ON dperm.grantee_principal_id = dprin.principal_id WHERE dprin.name = 'public';
Yes, we’re only using our database now!
So all is well with the world…
Until the day comes when you actually want to revoke permissions to that user. So you run the above code, copy the RevokeMe column and paste it into the management window. and you get…

GO
is a special little guy. It’s not exactly T-SQL. It’s a way of telling the SQL Server Management Studio (SSMS) to send everything before it, from the beginning of the script or the preceding GO
, to the SQL Server instance.
If you read the documents, the main point to take away is…
A Transact-SQL statement cannot occupy the same line as a GO command. However, the line can contain comments.
GO
is a special little snowflake and needs to be on his own line then. Simple enough if you know that SQL Server converts CHAR(10)
into a New Line.
If you didn’t know that, well you know that now….P.S. CHAR(13)
is a carriage return 😉
So let’s update our script with some CHAR(10)
and see what happens then.
SQL & BBQ, both work well with CHAR
SELECT dprin.name AS DatabasePrincipalName, OBJECT_NAME(dperm.major_id) AS ObjectName, dperm.permission_name AS PermissionName, N'USE ' + DB_NAME() + CHAR(10) + 'GO' + CHAR(10) + N'REVOKE ' + dperm.permission_name + N' ON OBJECT::' + OBJECT_NAME(dperm.major_id) + N' FROM ' + dprin.name COLLATE Latin1_General_CI_AS AS RevokeMe FROM sys.database_permissions AS dperm INNER JOIN sys.database_principals AS dprin ON dperm.grantee_principal_id = dprin.principal_id WHERE dprin.name = 'public';

Now, when we paste the RevokeMe column to a new window, we get…

…absolutely no difference. 🙂
Why am I smiling?
Here, around 500 words in, we get to the meat of our post. How do we keep new lines when copying in SQL Server?
Tools | Options | Query Results | Results to Grid | Retain CR/LF on copy or save
Two things need to be done here.
- This checkbox needs to be enabled.
CHECK! - A new window needs to be opened and used.
New window open, we run our script again, and this time, when we copy and paste the results, we get…

Dessert:
So if you are using T-SQL to create scripts, and you’re having this problem with GO
or just new lines in general, make sure that the “retain CR/LF on copy and save” checkbox is ticked.
Now, improve that script more, throw it in a stored procedure, and you never know, it may be semi-useful. 🙂
Yes!! This was bugging me recently, thanks for reminding me where that option was. =)