A resposta simples é "Você não pode realmente proteger contra injeção de SQL no nível do banco de dados". Uma vez que eles estejam conectados ao banco de dados com uma consulta em mãos, seu banco de dados irá executá-lo - se alguém tiver injetado maldade nesse SQL, o melhor que você pode esperar é mitigar o dano que eles podem causar.
Em termos de atenuação de danos, o que você já descreveu é uma ótima abordagem: restringir cada script a uma conta de usuário do banco de dados limitada ao acesso mínimo exigido pelo script (Selecionar, Inserir, Atualizar, Excluir e somente ao específico subconjunto de tabelas que o script deve tocar).
Isso não protege seu banco de dados de injeção de SQL - limita apenas a quantidade de dados que alguém pode roubar (ou destruir) com base no script que eles comprometeram. Um atacante determinado provavelmente atacará primeiro os scripts "interessantes", que têm os dados mais procurados que desejam em primeiro lugar.
Em termos de problemas imprevistos, a separação em funções do usuário pode fornecer apenas um ganho mínimo de segurança (se você tiver muitas consultas complexas e scripts de tabela cruzada que executam várias ações) com o risco de quebra severa ( especialmente se você tiver muitas consultas cruzadas complexas de scripts que fazem várias coisas).
É interessante notar que a auditoria do seu banco de dados neste nível provavelmente levará tanto tempo (se não mais) do que a substituição de todas as suas chamadas atuais com consultas parametrizadas apropriadas que tornam os ataques de injeção SQL difíceis ou impossíveis.