Uma Function em um banco de dados é muito similar a uma função em uma linguagem de programação comum, podendo até mesmo ser criada com uma linguagem de programação como Java, para os bancos de dados Oracle e IBM DB2 ou uma rotina CLR para o banco de dados MSSQL, entretanto possuem varias diferenças entre os diferentes bancos de dados.
Uma Function padrão pode ser do tipo Escalar que normalmente retorna um valor ou pode ser do tipo Tabela, que retorna uma tabela, porem dependendo do banco de dados utilizado, podem existir vários outros tipos de retornos ou também de funções, por este motivo é recomendado que você acesse os links oficiais a seguir para saber mais detalhes sobre as funções:
Oracle: Create Function
IBM DB2: Create Function
Microsoft SQL Server: Create Function
O programa abaixo é muito similar ao programa anterior que cria uma trigger, porem o calculo do campo SLIQUIDO é efetuado através de uma função do mesmo nome, na query que retorna o set de dados para a grade, você pode notar que esta função possui uma sintaxe muito semelhante as funções ou métodos do qual você já está acostumado, exceto pelo banco de dados MSSQL que necessita que o proprietário da função seja declarado antes do nome da função.
Exemplo:
Neste exemplo utilizamos uma simples função escalar para efetuar um calculo e retornar um valor, utilize o script abaixo para criar os objetos necessários para cada banco de dados ou o banco de dados da sua preferencia.
SQL
Oracle
create table Funcionarios(
ID_Funcionario NUMBER(5),
Nome VARCHAR2(30),
Sobrenome VARCHAR2(70),
Cargo VARCHAR2(30),
Salario NUMBER(9,2));
-- Cria Funcionarios
Insert into FUNCIONARIOS values (1,'Steve','Gates','Programador',2550.56);
Insert into FUNCIONARIOS values (2,'Bill','Jobs','Diretor',5143.71);
Insert into FUNCIONARIOS values (3,'Wozniak','Gates','Desenvolvedor', 4389.21);
-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
ID_FUNCIONARIO NUMBER,
PORCENTAGEM NUMBER(9,2));
-- Cria tabela de lançamentos de descontos
Create table SALARIO (
ID_FUNCIONARIO NUMBER,
DATA_LANC DATE,
VDESCONTO NUMBER(9,2));
-- Deleta dados antigos
-- Caso utlizou exemplos anteriores
delete from desconto;
delete from salario;
-- Cria trigger na tabela Desconto
create or replace TRIGGER DESCONTO_INSERT
BEFORE INSERT ON DESCONTO
FOR EACH ROW
-- Declara variáveis
DECLARE pID NUMBER;
pSalario NUMBER(9,2);
pPorcentagem NUMBER(9,2);
BEGIN
-- Alimenta variáveis com os valores a serem inseridos
pID := :new.ID_FUNCIONARIO;
pPorcentagem := :new.PORCENTAGEM;
-- Seleciona Salario do funcionario corrente
Select SALARIO INTO pSalario FROM FUNCIONARIOS
WHERE ID_FUNCIONARIO = pID;
-- insere na tabela de lançamentos de salario
Insert into SALARIO
values (
pID,
SYSDATE,
(pSalario * pPorcentagem)/100);
END DESCONTO_INSERT;
-- Cria Função
Create or replace function
sLiquido(sal IN NUMBER, vdesc IN NUMBER)
RETURN NUMBER IS resultado NUMBER (9,2);
BEGIN
resultado := sal - vdesc;
return (resultado);
END;
DB2
create table Funcionarios (
ID_Funcionario INTEGER,
Nome VARCHAR(30),
Sobrenome VARCHAR(70),
Cargo VARCHAR(30),
Salario NUMERIC(9,2))@
Insert into FUNCIONARIOS values (1,'Steve','Gates','Programador',2550.56)@
Insert into FUNCIONARIOS values (2,'Bill','Jobs','Diretor',5143.71)@
Insert into FUNCIONARIOS values (3,'Wozniak','Gates','Desenvolvedor', 4389.21)@
-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
ID_FUNCIONARIO INTEGER,
PORCENTAGEM DECIMAL(9,2))@
-- Cria tabela de lançamentos de descontos
Create table SALARIO (
ID_FUNCIONARIO INTEGER,
DATA_LANC DATE,
VDESCONTO DECIMAL(9,2))@
-- Deleta dados antigos
-- Caso utlizou exemplos anteriores
delete from desconto@
delete from salario@
-- Cria trigger na tabela Desconto
create TRIGGER DESCONTO_INSERT
BEFORE INSERT ON DESCONTO
REFERENCING NEW AS N
FOR EACH ROW
P1: BEGIN
-- Declara variáveis
DECLARE pID NUMBER;
DECLARE pSalario DECIMAL(9,2);
DECLARE pPorcentagem DECIMAL(9,2);
-- Alimenta variáveis com os valores a serem inseridos
SET pID = N.ID_FUNCIONARIO;
SET pPorcentagem = N.PORCENTAGEM;
-- Seleciona Salario do funcionario corrente
Select SALARIO INTO pSalario FROM FUNCIONARIOS
WHERE ID_FUNCIONARIO = pID;
-- insere na tabela de lançamentos de salario
Insert into SALARIO
values (
pID,
SYSDATE,
(pSalario * pPorcentagem)/100);
END P1
-- Cria Função
CREATE FUNCTION sLiquido (sal Decimal, vdesc Decimal)
RETURNS DECIMAL (9,2)
NO EXTERNAL ACTION
F1: BEGIN ATOMIC
DECLARE resultado DECIMAL(9,2);
SET resultado = sal - vdesc;
RETURN resultado;
END
MSSQL
create table Funcionarios (
ID_Funcionario Int,
Nome VARCHAR(30),
Sobrenome VARCHAR(70),
Cargo VARCHAR(30),
Salario Decimal(9,2));
Insert into FUNCIONARIOS values (1,'Steve','Gates','Programador',2550.56);
Insert into FUNCIONARIOS values (2,'Bill','Jobs','Diretor',5143.71);
Insert into FUNCIONARIOS values (3,'Wozniak','Gates','Desenvolvedor', 4389.21);
-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
ID_FUNCIONARIO INT,
PORCENTAGEM DECIMAL(9,2));
-- Cria tabela de lançamentos de descontos
Create table SALARIO (
ID_FUNCIONARIO INT,
DATA_LANC DATE,
VDESCONTO DECIMAL(9,2));
-- Deleta dados antigos
-- Caso utlizou exemplos anteriores
delete from desconto;
delete from salario;
-- Cria trigger na tabela Desconto
create TRIGGER DESCONTO_INSERT ON
DESCONTO AFTER INSERT AS
BEGIN
-- Declara variáveis
DECLARE @pID Int,
@pSalario DECIMAL(9,2),
@pPorcentagem DECIMAL(9,2);
-- Alimenta variáveis com os valores a serem inseridos
Select @pID = ID_FUNCIONARIO,
@pPorcentagem = PORCENTAGEM
from inserted;
-- Seleciona Salario do funcionario corrente
Select @pSalario = SALARIO FROM FUNCIONARIOS
WHERE ID_FUNCIONARIO = @pID;
-- insere na tabela de lançamentos de salario
Insert into SALARIO
values (
@pID,
GETDATE(),
(@pSalario * @pPorcentagem)/100);
END;
-- Cria função
Create function sLiquido(@sal decimal, @vdesc decimal)
Returns decimal(9,2) as
Begin
return(@sal-@vdesc);
end
Java
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
public class Cursor implements ActionListener, ItemListener {
// Cria componentes
private JTable tabela;
private JRadioButton banco1;
private JRadioButton banco2;
private JRadioButton banco3;
private JButton botao;
private JLabel lid_funcionario;
private JLabel lporcentagem;
private JTextField tid_funcionario;
private JTextField tporcentagem;
// Declara objetos de conexão
private static Connection conn;
private static Statement query;
private static String bancodedados;
public void conectar(String login, String senha) {
// Verifica strings de conexão
// ORACLE
if (bancodedados == "oracle") {
try {
// Define Driver de conexão JDBC thin
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:xe", login, senha);
// Executa pedido SQL
query = conn.createStatement();
}
catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
// DB2
if (bancodedados == "db2") {
try {
// Define Driver de conexão JDBC
Class.forName("com.ibm.db2.jcc.DB2Driver");
conn = DriverManager.getConnection(
"jdbc:derby:net://localhost:50000/deva", login, senha);
// Executa pedido SQL
query = conn.createStatement();
// JOptionPane.showMessageDialog(menssagem,
// "Conexão Efetuada com sucesso!");
}
catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
catch (SQLException ex) {
// JOptionPane.showMessageDialog(menssagem, "Erro na conexão!");
ex.printStackTrace();
}
}
// MICROSOFT SQL SERVER
if (bancodedados == "mssql") {
try {
// Define Driver de conexão JDBC
String URL = "jdbc:sqlserver://localhost\\SQLEXPRESS:1433;databaseName=devaberto"
+ ";user=" + login + ";password=" + senha;
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
conn = DriverManager.getConnection(URL);
// Executa pedido SQL
query = conn.createStatement();
}
catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
}
public void executaSQL(String sql) {
// Cria nova instrução SQL
Statement trigger;
;
try {
trigger = conn.createStatement();
trigger.execute(sql);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public ResultSet retornaTabela() throws SQLException {
// Cria nova instrução SQL
Statement query;
query = conn.createStatement();
String sql;
// Cria proprietario do banco de dados
String owner = "dbo.";
// SQL Server requer o proprietario para que a função seja executada
if (bancodedados != "mssql") owner = "";
// Verfica banco de dados e passa script SQL
sql = "Select A.ID_FUNCIONARIO, " + "A.NOME, " + " A.CARGO, "
+ " A.SALARIO, " + "B.PORCENTAGEM, " + "C.VDESCONTO, "
+ "C.DATA_LANC, " + owner
// Executa função SLIQUIDO - retorna o calculo do salario liquido.
+ "SLIQUIDO(A.SALARIO, C.VDESCONTO) AS SLIQUIDO "
+ "from FUNCIONARIOS A, DESCONTO B, SALARIO C " + "Where "
+ "A.ID_FUNCIONARIO = B.ID_FUNCIONARIO AND "
+ "A.ID_FUNCIONARIO = C.ID_FUNCIONARIO";
// Executa Script
ResultSet dados = query.executeQuery(sql);
// Retorna set de dados
return dados;
}
// Modelo
public static DefaultTableModel criaTableModel(ResultSet rs)
throws SQLException {
// Cria um modelo de tabela
ResultSetMetaData metaData = rs.getMetaData();
// Retorna as colunas
Vector<String> colunas = new Vector<String>();
int columnCount = metaData.getColumnCount();
for (int column = 1; column <= columnCount; column++) {
colunas.add(metaData.getColumnName(column));
}
// Retorna dados
Vector<Vector<Object>> dados = new Vector<Vector<Object>>();
while (rs.next()) {
Vector<Object> vector = new Vector<Object>();
for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
vector.add(rs.getObject(columnIndex));
}
dados.add(vector);
}
return new DefaultTableModel(dados, colunas);
}
public void itemStateChanged(ItemEvent arg0) {
// Verifica item banco de dados selecionado
Object fonte = arg0.getItemSelectable();
int estado = arg0.getStateChange();
if (estado == arg0.SELECTED) {
if (fonte == banco1) {
bancodedados = "oracle";
}
if (fonte == banco2) {
bancodedados = "db2";
}
if (fonte == banco3) {
bancodedados = "mssql";
}
}
}
public void actionPerformed(ActionEvent arg0) {
// Efetua login no banco de dados
Cursor acesso = new Cursor();
if (bancodedados == "oracle") {
acesso.conectar("daberto", "p@55w0rd");
}
if (bancodedados == "db2") {
acesso.conectar("db2admin", "p@55w0rd");
}
if (bancodedados == "mssql") {
acesso.conectar("devaberto", "p@55w0rd");
}
try {
// Executa Trigger (Tabela Desconto)
acesso.executaSQL("insert into DESCONTO VALUES ("+ tid_funcionario.getText() +
", " + tporcentagem.getText() + ")");
// Executa Intrução SQL
tabela.setModel(criaTableModel(acesso.retornaTabela()));
} catch (SQLException e) {
e.printStackTrace();
}
}
public Container criaPainel() throws SQLException {
// Cria painel principal
JPanel painel = new JPanel();
// Seleciona layout
painel.setLayout(new BoxLayout(painel, BoxLayout.PAGE_AXIS));
painel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
// Cria painel de escolha de conexão
JPanel pescolha = new JPanel();
pescolha.setLayout(new BoxLayout(pescolha, BoxLayout.LINE_AXIS));
pescolha.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
ButtonGroup grupo = new ButtonGroup();
// Cria componentes de radio
banco1 = new JRadioButton("Oracle");
banco2 = new JRadioButton("IBM DB2");
banco3 = new JRadioButton("Microsoft SQL");
// Agrupa botões de radio
grupo.add(banco1);
grupo.add(banco2);
grupo.add(banco3);
// Cria ouvinte dos botões
banco1.addItemListener(this);
banco2.addItemListener(this);
banco3.addItemListener(this);
// Seleciona primeira conexão
banco1.setSelected(true);
// Adiciona botões ao painel
pescolha.add(banco1);
pescolha.add(banco2);
pescolha.add(banco3);
// Efetua primeira conexão ao banco (ORACLE)
Cursor acesso = new Cursor();
acesso.conectar("daberto", "myoracle123");
// Cria modelo de tabela
tabela = new JTable(criaTableModel(acesso.retornaTabela()));
// Adiciona um painel de rolagem
JScrollPane rolar = new JScrollPane(tabela);
// Cria painel do botão
JPanel pbotao = new JPanel(new GridLayout(0, 5, 10, 10));
// Cria botão
lid_funcionario = new JLabel("Código Func:");
lporcentagem = new JLabel("Porcentagem:");
tid_funcionario = new JTextField();
tporcentagem = new JTextField();
botao = new JButton("Inserir");
botao.addActionListener(this);
// Define foco do cursor
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
tid_funcionario.requestFocus();
}
});
// Adiciona botão ao painel
pbotao.add(lid_funcionario);
pbotao.add(tid_funcionario);
pbotao.add(lporcentagem);
pbotao.add(tporcentagem);
pbotao.add(botao);
// componentes ao painel principal
painel.add(pescolha);
painel.add(rolar);
painel.add(Box.createVerticalStrut(10));
painel.add(pbotao);
return painel;
}
public static void criaGUI() {
// Cria formulario
JFrame formulario = new JFrame("Desenvolvimento Aberto - Triggers");
formulario.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// cria painel de conteudo
Cursor acesso = new Cursor();
try {
formulario.setContentPane(acesso.criaPainel());
}
catch (SQLException e) {
e.printStackTrace();
}
// Exibe o formulario
formulario.setSize(700, 300);
formulario.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Cria e mostra a GUI
criaGUI();
}
});
}
}


