Uma View ou visão em português, é uma tabela virtual. A View não possui um armazenamento de dados permanente associado a ela, mas é baseada em outra tabela ou tabelas. Existem vários tipos de visões, elas podem variar suas funcionalidades de banco de dados para banco de dados, as Views mais comum são do tipo padrão, particionada ou materializada.
A visão fornece uma forma alternativa de olhar os dados em uma ou mais tabelas. A vista é uma especificação chamada de uma tabela de resultados. Conceitualmente, a criação de um ponto de vista é como o uso de binóculos. Você pode olhar através de binóculos para ver uma paisagem inteira ou olhar para uma imagem específica dentro da paisagem, como uma árvore. Da mesma forma, você pode criar uma visão que combina dados de diferentes tabelas de base ou criar uma visão limitada de uma tabela que omite dados. Na verdade, estes são os motivos mais comuns para usar um ponto de vista. Combinando informações de tabelas de base simplifica a obtenção de dados para o usuário final, e limitar os dados que um usuário pode ver é útil para fins de segurança.
Devido aos vários tipos diferentes de Views e suas respectivas diferenças de funcionalidades entre os bancos de dados Oracle, IBM DB2 e MSSQL é recomendado que você utilize os links oficiais para referencia:
Oracle: Create View
IBM DB2: Create View
Microsoft SQL Server: Create View
Algo Extremamente Útil Sobre Views
As Views são essenciais para uma boa performance de um sistema que manipula dados, elas são uteis de muitas maneiras diferentes, todos os sistemas de grande porte utilizam tipos de View.
As Views acrescentam performance a aplicação, podem conter constraints e índices, podem criar visões baseadas em formato XML, podem ser utilizadas para fins de segurança, podem ser criadas a partir de tabelas particionadas alocadas em vários servidores diferentes e retornar uma visão única, são fundamentais na criação de complexos relatórios, modelo de dados para exportação e até no manuseio de cadastros.
As Views possuem um recurso muito útil quando unidas ao evento INSTEAD OF de uma Trigger, na verdade este tipo de evento foi desenvolvido especialmente para a utilização em conjunto com uma View (exceto para banco de dados MSSQL que permite o uso em tabelas comuns). A utilização do evento “ao invés de” em uma View permite que o desenvolvedor ganhe a maior performance possível na distribuição de dados baseados em uma única visão para varias tabelas físicas contidas em locais diferentes.
Isto acontece porque, por exemplo, um formulário de cadastramento complexo geralmente é composto de varias tabelas interligadas pelo seu identificador, a combinação View–Trigger permite que você retorne em uma única pesquisa todo o cadastro utilizando um único acesso. Quando disparado um evento para criar um cadastro novo ou modificar um cadastro existente em cima de uma View, automaticamente uma Trigger “ao invés de inserir” ou “ao invés de alterar” pode distribuir todos os dados alimentados pelo usuário em cada tabela especifica, tendo em seu beneficio, que todo o processo esta sendo efetuado dentro do motor do banco de dados.
Visual Studio
Você encontra um walkthrough de como instalar os bancos de dados, seus drivers e a configuração da IDE Visual Studio na categoria SQL e C++, use a imagem abaixo para referencia de como criar design utilizando, 1 GroupBox, 8 StaticTexts, 7 EditControls e 5 Buttons:
Exemplo:
Neste exemplo utilizamos o conceito básico de uma View em conjunto com o evento INSTEAD OF de uma Trigger, no programa abaixo o método de inserção esta completo, fica como exercício criar o método INSTEAD OF UPDATE e INSTEAD OF DELETE.
Você encontra uma visão contendo duas tabelas relacionadas, a tabela Funcionários e Desconto, e a partir de uma trigger utilizamos o evento “ao invés de inserir” para distribuir os dados para suas respectivas tabelas. Na aplicação C++ o campo porcentagem possui cor diferente pois se encontra em outra tabela, você pode utilizar este exemplo básico para criar cadastros mais complexos.
* Para referencia sobre as triggers utilize nosso post C++ com o tópico Triggers.
** Você encontra este mesmo programa utilizando SQL direto na aplicação, clicando aqui.
SQL
Oracle
-- Cria tabela de funcionarios
create table Funcionarios(
ID_Funcionario NUMBER(5),
Nome VARCHAR2(30),
Sobrenome VARCHAR2(70),
Cargo VARCHAR2(30),
Salario NUMBER(9,2));
-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
ID_FUNCIONARIO NUMBER,
PORCENTAGEM NUMBER(9,2));
-- Cria View (Visão) do Cadastro de funcionarios
Create or Replace View CadFuncionario as
Select
A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
A.CARGO, A.SALARIO, B.PORCENTAGEM
from FUNCIONARIOS A, DESCONTO B
Where
A.ID_FUNCIONARIO = B.ID_FUNCIONARIO;
-- Cria Trigger Ao inves de inserir sobre a View
create or replace TRIGGER CADFUNC_INSERT
INSTEAD OF INSERT ON CadFuncionario
FOR EACH ROW
BEGIN
-- Insere dados na tabela de Funcionario
Insert into FUNCIONARIOS values (
:new.ID_FUNCIONARIO,
:new.NOME,
:new.SOBRENOME,
:new.CARGO,
:new.SALARIO);
-- Insere dados na tabela de Desconto
Insert into DESCONTO values (
:new.ID_FUNCIONARIO,
:new.PORCENTAGEM);
END CADFUNC_INSERT;
IBM DB2
-- Desenvolvimento Aberto --
-- Atente-se para o terminador de instruções
-- o IBM DATA STUDIO não consegue utilizar
-- Begin... END com scripts sql
-- Mude o terminador para o caractere @
-- para mudar clique com o botão direito do mouse aqui!!!
-- Cria tabela de funcionarios
create table Funcionarios (
ID_Funcionario INTEGER,
Nome VARCHAR(30),
Sobrenome VARCHAR(70),
Cargo VARCHAR(30),
Salario NUMERIC(9,2))@
-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
ID_FUNCIONARIO INTEGER,
PORCENTAGEM DECIMAL(9,2))@
-- Cria View (Visão) do Cadastro de funcionarios
Create or Replace View CadFuncionario as
Select
A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
A.CARGO, A.SALARIO, B.PORCENTAGEM
from FUNCIONARIOS A, DESCONTO B
Where
A.ID_FUNCIONARIO = B.ID_FUNCIONARIO@
-- Cria Trigger Ao inves de inserir sobre a View
create or replace TRIGGER CADFUNC_INSERT
INSTEAD OF INSERT ON CadFuncionario
REFERENCING NEW AS N
FOR EACH ROW
T1: BEGIN
-- Insere dados na tabela de Funcionario
Insert into FUNCIONARIOS values (
N.ID_FUNCIONARIO,
N.NOME,
N.SOBRENOME,
N.CARGO,
N.SALARIO);
-- Insere dados na tabela de Desconto
Insert into DESCONTO values (
N.ID_FUNCIONARIO,
N.PORCENTAGEM);
END T1
MSSQL Server
-- Cria tabela de funcionarios
create table Funcionarios (
ID_Funcionario Int,
Nome VARCHAR(30),
Sobrenome VARCHAR(70),
Cargo VARCHAR(30),
Salario Decimal(9,2));
-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
ID_FUNCIONARIO INT,
PORCENTAGEM DECIMAL(9,2));
-- Cria View (Visão) do Cadastro de funcionarios
Create View CadFuncionario as
Select
A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
A.CARGO, A.SALARIO, B.PORCENTAGEM
from FUNCIONARIOS A, DESCONTO B
Where
A.ID_FUNCIONARIO = B.ID_FUNCIONARIO;
-- Cria Trigger Ao inves de inserir sobre a View
create Trigger CADFUNC_INSERT
ON CadFuncionario INSTEAD OF INSERT as
BEGIN
-- Insere dados na tabela de Funcionario
Insert into FUNCIONARIOS
Select
ID_FUNCIONARIO,
NOME,
SOBRENOME,
CARGO,
SALARIO
from inserted;
-- Insere dados na tabela de Desconto
Insert into DESCONTO
Select
ID_FUNCIONARIO,
PORCENTAGEM
from inserted
END;
C++
Classe – Arquivo .h
// CamposcppDlg.h : header file
//
#pragma once
// Inclui classe de banco de dados MFC
#include "afxdb.h"
#include "afxwin.h"
// CCamposcppDlg dialog
class CCamposcppDlg : public CDialogEx
{
public:
CCamposcppDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_CAMPOSCPP_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
// Cria métodos e objetos da classe
CDatabase db;
// Esta variavel define o banco de dados
// oracle = Oracle Database
// db2 = IBM DB2
// mssql = MSSQL Server
CString m_db = L"oracle";
// Conecta ao banco de dados
void conectarDB(CString banco);
// Variaveis Edits
CEdit m_pesquisa;
CEdit m_codigo;
CEdit m_pnome;
CEdit m_snome;
CEdit m_cargo;
CEdit m_salario;
CEdit m_porcentagem;
// Variaveis Botões
CButton m_apagar;
CButton m_novo;
// Eventos
afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
afx_msg void OnBnClickedButton1();
afx_msg void OnBnClickedButton2();
afx_msg void OnBnClickedButton3();
afx_msg void OnBnClickedButton4();
afx_msg void OnBnClickedButton5();
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};
Classe – Arquivo .cpp
// CamposcppDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Camposcpp.h"
#include "CamposcppDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CCamposcppDlg::CCamposcppDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CCamposcppDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CCamposcppDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT6, m_pesquisa);
DDX_Control(pDX, IDC_EDIT1, m_codigo);
DDX_Control(pDX, IDC_EDIT2, m_pnome);
DDX_Control(pDX, IDC_EDIT3, m_snome);
DDX_Control(pDX, IDC_EDIT4, m_cargo);
DDX_Control(pDX, IDC_EDIT5, m_salario);
DDX_Control(pDX, IDC_BUTTON5, m_apagar);
DDX_Control(pDX, IDC_BUTTON2, m_novo);
DDX_Control(pDX, IDC_EDIT7, m_porcentagem);
}
BEGIN_MESSAGE_MAP(CCamposcppDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CCamposcppDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON2, &CCamposcppDlg::OnBnClickedButton2)
ON_WM_SHOWWINDOW()
ON_BN_CLICKED(IDC_BUTTON3, &CCamposcppDlg::OnBnClickedButton3)
ON_BN_CLICKED(IDC_BUTTON4, &CCamposcppDlg::OnBnClickedButton4)
ON_BN_CLICKED(IDC_BUTTON5, &CCamposcppDlg::OnBnClickedButton5)
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
BOOL CCamposcppDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
return TRUE;
}
void CCamposcppDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this);
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
HCURSOR CCamposcppDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
// ************************ Desenvolvimento Aberto
// Nosso código começa aqui
void CCamposcppDlg::conectarDB(CString banco)
{
// Cria string de conexão
CString dns, usuario, senha;
// Define banco de dados
if (banco == "oracle")
{
dns = L"OracleXE";
usuario = L"daberto";
senha = L"p@55w0rd";
}
if (banco == "db2")
{
dns = L"IBMDB2";
usuario = L"db2admin";
senha = L"p@55w0rd";
}
if (banco == "mssql")
{
dns = L"MSSQLSERVER";
usuario = L"devaberto";
senha = L"p@55w0rd";
}
// Cria string de conexão ODBC
CString conexao;
// Cria string de conexão
conexao = L"DSN=" + dns + L";UID=" + usuario + L";PWD=" + senha;
// Abre conexão
db.OpenEx(conexao, 0);
}
void CCamposcppDlg::OnBnClickedButton1()
{
// Define variaveis
CString codigo;
CString m_campo;
// Referincia objeto statico
CWnd * p_rotulo;
// Associa objeto statico
p_rotulo = GetDlgItem(IDC_Rotulo);
p_rotulo->SetWindowTextW(L"Database - Cadastro Funcionários - " + m_db);
// Conecta ao banco de dados
conectarDB(m_db);
// Cria um set de dados
CRecordset dados(&db);
// Cria pesquisa
m_pesquisa.GetWindowTextW(codigo);
dados.Open(CRecordset::forwardOnly,
L"Select * From CadFuncionario Where ID_FUNCIONARIO = " + codigo);
// Retorna dados por nome de campo e os exibe
// Oracle e o DB2 transformam os nomes de campos para maiusculo,
// basta efetuar um select na tabela de cada banco e você verá
// O MSSQL não faz esta mudança sendo assim você precisa mudar os campos
// do banco de dados MSSQL para que fique compativel com o ORACLE e DB2 ou
// encontrará um erro ao tentar utilizar a tabela que criamos anteriormente.
dados.GetFieldValue(L"ID_FUNCIONARIO", m_campo);
m_codigo.SetWindowTextW(m_campo);
dados.GetFieldValue(L"NOME", m_campo);
m_pnome.SetWindowTextW(m_campo);
dados.GetFieldValue(L"SOBRENOME", m_campo);
m_snome.SetWindowTextW(m_campo);
dados.GetFieldValue(L"CARGO", m_campo);
m_cargo.SetWindowTextW(m_campo);
dados.GetFieldValue(L"SALARIO", m_campo);
m_salario.SetWindowTextW(m_campo);
dados.GetFieldValue(L"PORCENTAGEM", m_campo);
m_porcentagem.SetWindowTextW(m_campo);
// Fecha o set de dados e a conexão
dados.Close();
db.Close();
}
void CCamposcppDlg::OnBnClickedButton2()
{
// Limpa componentes
m_codigo.SetWindowTextW(NULL);
m_pnome.SetWindowTextW(NULL);
m_snome.SetWindowTextW(NULL);
m_cargo.SetWindowTextW(NULL);
m_salario.SetWindowTextW(NULL);
m_porcentagem.SetWindowTextW(NULL);
// Define foco
CEdit* pesquisa;
pesquisa = (CEdit*)GetDlgItem(IDC_EDIT1);
GotoDlgCtrl(pesquisa);
}
void CCamposcppDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
CDialogEx::OnShowWindow(bShow, nStatus);
// Define foco inicial
CEdit* pesquisa;
pesquisa = (CEdit*)GetDlgItem(IDC_EDIT6);
GotoDlgCtrl(pesquisa);
}
// Cria método de menssagem
int menssagem(bool correto, LPCWSTR texto)
{
LPCWSTR msg;
if (correto)
{
msg = texto;
}
else
{
msg = texto;
}
// Cria nova caixa de menssagens
int msgboxID = MessageBox(
NULL,
msg,
(LPCWSTR)L"Conexão",
MB_ICONWARNING | MB_OK | MB_DEFBUTTON2
);
switch (msgboxID)
{
case IDOK:
break;
}
return msgboxID;
}
// Clique do botão inserir
void CCamposcppDlg::OnBnClickedButton3()
{
// Define variaveis para componentes
CString codigo;
CString pnome;
CString snome;
CString cargo;
CString salario;
CString porcentagem;
// conecta ao banco de dados
conectarDB(m_db);
// Recupara texto dos componentes
m_codigo.GetWindowTextW(codigo);
m_pnome.GetWindowTextW(pnome);
m_snome.GetWindowTextW(snome);
m_cargo.GetWindowTextW(cargo);
m_salario.GetWindowTextW(salario);
m_porcentagem.GetWindowTextW(porcentagem);
// Troca ponto decimal para o banco de dados
int i = salario.Replace(L",", L".");
// Cria instrução SQL
CString sql = L"Insert into CadFuncionario values ( " + codigo + ", " +
"'" + pnome + "', " +
"'" + snome + "', " +
"'" + cargo + "', " +
salario + ", " +
porcentagem + ")";
// Executa SQL
try
{
db.ExecuteSQL(sql);
menssagem(true, L"Dados inseridos com sucesso!");
db.Close();
}
catch (CDBException* pe)
{
menssagem(false, L"Erro ao inserir dados.");
db.Close();
}
}
// botão Updata
void CCamposcppDlg::OnBnClickedButton4()
{
// TODO: Criar Trigger INSTEAD OF UPDATE
}
void CCamposcppDlg::OnBnClickedButton5()
{
// TODO: Criar Trigger INSTEAD OF DELETE
}
HBRUSH CCamposcppDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
// Seleciona controle no dialogo e muda sua cor
if (pWnd->GetDlgCtrlID() == IDC_Porcentagem)
{
// RGB - Vermelho
pDC->SetTextColor(RGB(255, 0, 0));
pDC->SetBkMode(TRANSPARENT);
}
return hbr;
}



