How can I handle unwanted, non-erroneous situations better? When writing procedures, I occasionally encounter situations in which I want to abort the procedure, even if the situation didn't necessarily trigger an error.

Let's say, if I don't want John to be able to run this procedure, I'd do something like this:

IF @UserName = 'John'
BEGIN
    RAISERROR('John, get out', 16, 1);
    RETURN 1;
END


I don't really have a good reason for returning 1, it's mostly a remnant from shell scripting, and I'm open for better ways to do this.

Is there a better way of returning an error message and returning control to the caller for unwanted situations that aren't strictly speaking errors? I am not interested in reducing the amount of characters or lines of code. I just had a gut feeling saying "this is probably not the best way to solve this problem", and I was curious if there were smarter ways to do this.

One alternative could be by always using TRY/CATCH, since RAISERROR with a severity of 1-19 will hand control to the catch clause. 

Example:

BEGIN TRY
    PRINT 'Before RAISERROR';
    RAISERROR('Time for errors', 16, 1);
    PRINT 'After RAISERROR'
END TRY
BEGIN CATCH
    DECLARE @Msg NVARCHAR(255) = ERROR_MESSAGE()
    PRINT 'Inside CATCH'
    RAISERROR(@Msg, 16, 1)
END CATCH


Output: 

Before RAISERROR
Inside CATCH
Msg 50000, Level 16, State 1, Line 13
Time for errors


Con: Requires the presence of TRY/CATCH blocks.
Is there a more terse way of returning an error message and returning
  control to the caller for unwanted situations that aren't strictly
  speaking errors?


You can use THROW


  Raises an exception and transfers execution to a CATCH block of a
  TRY…CATCH construct ... If a TRY…CATCH construct is not available, the
  session is ended.


IF @UserName = 'John'
    THROW 50000, 'John, get out', 1;  


The above is somewhat more terse as it is just a single statement and doesn't need the RETURN so you can also drop the BEGIN and END