A maneira universal de armazenar um endereço / localização geográfica em um banco de dados é esta:
[Address] nvarchar(max) not null
Isso requer a menor quantidade de código de programação (e, portanto, reduz os custos de manutenção) e é totalmente compatível com qualquer endereço. No entanto, há três grandes problemas:
A falta de validação de dados significa que o campo pode ser usado para outros fins que não o armazenamento do endereço. Um dos propósitos é um ataque do DOS destinado a preencher o espaço do seu banco de dados digitando 2 GB de dados no campo de endereço.
Os dados armazenados dessa maneira tornam impossível processá-los para fins de business intelligence e mineração de dados. Por exemplo, quantos usuários são da Índia? Não há uma maneira fácil de saber, pois esses endereços não serão normalizados.
Os usuários podem digitar incorretamente um endereço incompleto ou claramente errado.
Para atenuar o primeiro problema, limite o campo ao que você considera um limite razoável. Pessoalmente, eu começaria com 1.000 caracteres e depois o reduziria com base no tamanho dos endereços inseridos pelos primeiros usuários quando você obtiver um conjunto de dados grande o suficiente.
Para atenuar os outros dois problemas, você pode usar uma API de terceiros que analisa endereços e apresenta os dados que contêm o país, cidade, código postal etc. Se possível, a API deve poder exibir o endereço em um mapa de volta ao usuário para reduzir o risco de o usuário inserir um endereço incompleto ou errado: a maioria dos usuários sabe onde mora, e ver uma posição diferente em um mapa daria a ele imediatamente uma pista de que eles deveriam verificar suas informações.
Observe que, independentemente da API que você usar, não será perfeita. Ele encontrará a maioria dos endereços, mas não todos. Isso significa que, se a API diz que o endereço não existe, mas o usuário insiste que sim, você deve, a priori, confiar no usuário, mesmo que ele esteja errado.
Isso também significa que você ainda deve armazenar a entrada do usuário original, lado a lado com o resultado da API. Isso significa que o esquema se torna:
[RawAddress] nvarchar(max) not null
[ParsedAddress] xml null