You can and should still parameterize your dynamic sql to make it truly safe. Your example query could be something like this.
declare @z int = 10
EXEC sp_executesql 'SELECT x FROM y WHERE MyColumn = @z', N'@z int', @z
Now we have created a parameterized query inside your dynamic sql and passed the parameter to the execution. This is NOT vulnerable to sql injection.
--EDIT--
Since you wanted an answer to the question of if your original query is vulnerable to sql injection I will demonstrate that it is in fact quite open. You are only dealing with single quotes which is truly on the tip of the iceberg when it comes to sql injection. Have you considered what happens if instead of a string they pass in a binary representation of a string?
Let's say your query is receiving a nvarchar(max) as a parameter. In my example I call this @BadCode. Now in my example I am not doing any harm to your system but in the wild this binary could be literally anything.
Here is a simple stored procedure with a pattern very close to what you demonstrated.
create procedure InjectionTest
(
@BadCode nvarchar(max)
) as
set @BadCode = REPLACE(@BadCode, '''', '')
EXEC sp_executesql @BadCode
GO
Now from the front end I am going to pass in the value 0x730065006C0065006300740020002A002000660072006F006D0020007300790073002E00640061007400610062006100730065007300. Again, this is harmless binary here. If you want to see simply put that inside a convert(varchar(max),...
Here is an example of the above procedure being called. The binary string coming in is what the user would pass in. Notice there are no single quotes in that.
declare @Test nvarchar(max) = 0x730065006C0065006300740020002A002000660072006F006D0020007300790073002E00640061007400610062006100730065007300
exec InjectionTest @Test
There are plenty of much longer explanations and more trickery but this demonstrates the basics of how this can easily be broken.