#SQL na unha: definindo estrutura do banco
Tags: database, sql, mysql, postgres
Published: 2022-01-27 21:37:08

Fala galera, chegamos ao segundo artigo sobre de banco de dados, caso ainda não tenha lido, já deixo aqui [o link para primeiro artigo](https://dev.to/erandirjunior/sql-na-unha-banco-de-dados-e-primeiros-comandos-h4o), não deixe de conferir, **leitura obrigatória**.

## Tipos de dados
Como vimos no primeiro artigo, bancos relacionais armazenam dados em tabelas, essas tabelas possuem colunas, e as colunas armazenam dados de tipos específicos. Recomendo olhar a documentação do SGBD que esteja utilizando para verificar quais tipos de dados são suportados. Em nosso caso, o **MySQL** aceita os seguintes tipos:
* Numeric Data Types
* Date and Time Data Types
* String Data Types
* Spatial Data Types
* The JSON Data Type

## Criando tabelas
Para **criar uma tabela**, execute o comando abaixo informando o nome da tabela, suas colunas, tipos e configurações extras:
```sql
CREATE TABLE user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL
);
```

O campo ***id***, foi o primeiro a ser definido. Ele só aceita dados do tipo ***int*** (inteiro), além do mais, esse campo é a nossa chave primária, ela será útil para criar referências, estudaremos isso posteriormente. Além disso, esse campo é único, ou seja, não pode existir dois registros com o mesmo valor.

Outra informação importante, é que configuramos esse campo como auto incremental, isso quer dizer que a cada novo registro, o valor desse campo será incrementado em 1, caso o valor não seja informado no momento de inserir um novo registro.

No segundo e terceiro campo, nomeamos como ***name*** e ***email***, atribuímos para ambos o tipo ***varchar***, que nada mais é que uma ***string***. Além disso, esse campo aceita até 255 caracteres. Outra configuração passada, é que esses campos não podem ser nulos, o preenchimento deles é obrigatório.

Um detalhe que gostaria de falar, é que chaves primárias não podem ser nulas, se vocês perceberem, não definimos essa configuração para nosso campo, mas isso já fica implícito.

Para **excluir qualquer tabela** do nosso banco, basta executar o comando abaixo, informando o nome da tabela:
```sql
DROP TABLE user;
```

Assim como não podemos ter bancos com o mesmo nome, **não podemos ter tabelas com o mesmo nome no mesmo banco**. Para não termos problemas, basta fazer uma verificação no momento de criar uma nova tabela, bem parecido com o que fizemos na criação de um _database_:
```sql
CREATE TABLE IF NOT EXISTS user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL
);
```

Podemos **adicionar um comentário à um campo**:
```sql
CREATE TABLE IF NOT EXISTS user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL COMMENT 'storage user name',
    email VARCHAR(255) NOT NULL COMMENT 'storage user email'
);
```

O comando a seguir mostra como está **estruturada nossa tabela**, com as colunas, tipos e configurações extras:
```sql
DESC TABLE user;
```
***Aconselho a usar o comando acima a cada nova alteração feita***.

Os comandos abaixo mostram como **adicionar um novo campo**, e ainda **seu local dentro da tabela**:
```sql
ALTER TABLE user ADD updated_at DATETIME; -- Adiciona uma coluna no final da tabela.

ALTER TABLE user ADD created_at TEXT AFTER updated_at; -- Adiciona uma coluna logo após a outra especificada.

ALTER TABLE user ADD new_field VARCHAR(255) FIRST; -- Adiciona uma coluna como se ela fosse a primeira da tabela.
```

Para **remover uma coluna**, basta rodar o comando abaixo informando o nome da tabela e a coluna a ser removida:
```sql
ALTER TABLE user DROP new_field;
```

Podemos **alterar o tipo, configurações, etc, de uma coluna**. Para isso, basta informar a tabela, coluna e as novas configurações do campo:
```sql
ALTER TABLE user MODIFY created_at DATETIME DEFAULT CURRENT_TIMESTAMP; -- aqui informamos que o campo created_at é do tipo data e ele tem um valor padrão caso o valor do campo não seja passado

ALTER TABLE user MODIFY updated_at DATETIME DEFAULT CURRENT_TIMESTAMP;
```

Podemos ter uma tabela, **no qual um ou mais campos tenham referência para outras tabelas**, rode o comando abaixo e observe atentamente cada campo e configuração informada:
```sql
create table if not exists product (
    id int primary key auto_increment,
    name varchar(255) not null,
    value double(10,2) not null,
    description text,
    user_id int not null,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    deleted_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    foreign key(user_id) references user(id)
);
```

Na tabela acima, definimos nosso campo primário e algumas colunas e configurações. Nosso ponto de observação fica por conta do campo ***user_id*** que **faz referência a tabela _user_**.

O campo *user_id* faz referência a tabela *user* e especificamente a chave primária dessa tabela, isso significa que esse campo **só pode ser preenchido por valores existentes na chave primária da tabela _user_**.

## Um pouco mais sobre referências
Uma tabela pode ter vários campos que podem fazer tanto referência a outras tabelas, como também a própria tabela. Lembre-se de deixar nulo um campo que faz referência a mesma tabela, para não gerar erros.

E por fim, podemos **listar todas as tabelas do banco**:
```sql
SHOW TABLES;
```

Ufa! Esse artigo ficou um pouco grande, mas foi necessário, espero que estejam curtindo. Até o próximo artigo.