O Google App Engine permite que você construa aplicações web nos mesmos sistemas escaláveis ​​que as aplicações criadas pelo Google.  Os aplicativos App Engine são fáceis de construir, fácil de manter e fácil de escalar. Com o Google App Engine, não há servidores para manter. Se você acabou de fazer upload de seu aplicativo, ele está pronto para servir a seus usuários.

Ao contrario do Windows e Mac o Linux não possui o Google App Engine Launcher, deste modo todo o manuseio, incluindo compilação, servidor, e  deploy deve ser feito pelo terminal do Linux, por outro lado o Linux já contempla por default todas as ferramentas no qual usaremos, como a instalação do Python 2.7.x e o editor GEdit para a programação Python, então só nos resta baixar o Google App Engine SDK que pode ser baixado clicando aqui.

Computação nas Nuvens

O conceito de computação em nuvem em inglês, Cloud Computing, refere-se à utilização da memória e da capacidade de armazenamento e cálculo de computadores e servidores compartilhados e interligados por meio da Internet, seguindo o princípio da computação em grade.

O armazenamento de dados é feito em serviços que poderão ser acessados de qualquer lugar do mundo, a qualquer hora, não havendo necessidade de instalação de programas ou de armazenar dados. O acesso a programas, serviços e arquivos é remoto, através da Internet – daí a alusão à nuvem. O uso desse modelo (ambiente) é mais viável do que o uso de unidades físicas.

SandBox

O SandBox, em português, caixa de areia (onde as crianças brincam e o gato faz caca, nem precisa explicar, não é?), é um ambiente de desenvolvimento utilizado para desenvolvimentos primários, existem vários tipos de ambiente SandBox e geralmente estão associados a uma metodologia de desenvolvimento. Por exemplo, desenvolvimento de grandes aplicações, uma equipe de desenvolvedores podem utilizar o ambiente de SandBox para criar e testar aplicações sem risco de interferir com a configuração do ambiente de desenvolvimento oficial, após a aplicação ser testada ela passa para um ambiente DEV oficial e o ambiente de SandBox é descartado, sendo constantemente atualizado com uma copia do ambiente de desenvolvimento da empresa. Em desenvolvimento para a web, as empresas que permitem programação em seus ambientes, disponibilizam um ambiente de SandBox para que o usuário aprenda a criar aplicações utilizando virtualizações dos seus ambientes de desenvolvimento, porem sem interferir nos mesmos.

Para permitir que o Google App Engine distribua os pedidos para aplicações em vários servidores web, e para evitar uma aplicação de interferir com a outra, o aplicativo é executado em um ambiente de sandboxrestrito.

Google SandBox Python: https://developers.google.com/appengine/docs/python/#Python_The_sandbox

O que você deve saber sobre o Google Cloud

  • O nome da aplicação é chamado de AppID e deve ser único para não haver colisão de nome na web.
  • As boas praticas recomendam criar nomes de aplicação e diretórios utilizando caracteres minúsculos.
  • O servidor web local do Google App Engine é baseado na tecnologia Apache.
  • As portas locais não devem colidir com outras portas em uso por algum servidor web em seu computador.
  • O Linux não possui a ferramenta Google App Engine Launcher e toda sua manipulação deve ser feita pelo terminal.

 

Programando nas nuvens com o Google App Engine

1 – Para desencargo de consciência,  precisamos testar se já possuímos a versão do Python 2.7.x já instalada, use o comando:


/usr/bin/env python -V

Versão Python

Versão Python

2 – Descompacte o arquivo baixado na sua pasta Home do sistema operacional, que em português chama-se Pasta Pessoal, crie uma nova pasta para nossa aplicação, chame de GoogleApp, deste modo você terá duas pastas adicionais em seu diretório home do Linux, a pasta do SDK chamada google_appengine e GoogleApp na qual iremos criar nossos arquivos fonte.

Descompactar arquivo Zip

Descompactar arquivo Zip

3 – Uma App Cloud do Google é composta de basicamente de dois arquivos, um de extensão yaml que contem os parâmetros de sua aplicação, incluindo o seu AppID e de um arquivo .py que contem o programa de código Python. Use o GEdit do Linux e crie os arquivos app.yaml e main.py e utilize o código abaixo para escrever cada arquivo:

Código Fonte

Código Fonte

4 – Com os arquivos criados no diretório GoogleApp no qual criamos anteriormente, precisamos iniciar o servidor local, utilize a linha abaixo para iniciar o servidor:


~/google_appengine/dev_appserver.py ~/GoogleApp/

Inicia Servidor - App Engine

Inicia Servidor – App Engine

5 – Com o servidor iniciado, abra o seu navegador web e digite o seguinte endereço: http://localhost:8080/

Localhost - porta: 8080

Localhost – porta: 8080

6 – Abra uma outra aba no navegador e digite o endereço do Google App Engine para que possamos criar nosso projeto nos servidores Cloud do Google, já presumimos que você tenha uma conta do Google: https://appengine.google.com/

Google Cloud - Aplicação

Google Cloud – Aplicação

7 – Coloque o nome de sua App de acordo com o conceito de AppID do Google Cloud, este nome deve ser o mesmo contido no seu arquivo app.yaml e deve ser único, preencha uma descrição e clique em criar aplicação:

Cloud - AppID

Cloud – AppID

8 – Vamos efetuar um Deploy para os servidores do Google, isto significa que vamos compilar o programa Python e efetuar um Upload para as nuvens, utilize o seguinte comando para efetuar este procedimento, e-mail e senha serão requeridos:


~/google_appengine/appcfg.py update ~/GoogleApp/

Deploy - nuvens

Deploy – nuvens

9 – Agora é só testar o endereço de sua aplicação nos servidores Cloud do Google, o endereço é composto de sua AppID + .appspot.com:

App Google Cloud

App Google Cloud

Exemplo:

Neste exemplo criamos uma aplicação nas nuvens utilizando a tecnologia Cloud do Google e a linguagem de programação Python:

Utilize este link para ver a aplicação nas nuvens: http://damyapplinux.appspot.com/

Yaml

application: damyapplinux
version: 1
runtime: python27
api_version: 1
threadsafe: yes

handlers:
- url: /favicon\.ico
  static_files: favicon.ico
  upload: favicon\.ico

- url: .*
  script: main.app

libraries:
- name: webapp2
  version: "2.5.2"

Python

#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import webapp2

class MainHandler(webapp2.RequestHandler):
    def get(self):
        self.response.write('<h1>Desenvolvimento Aberto</h1>' + \
                            '</br>Hello world!</br>' + \
                            '<strong>' + \
                            '<font size="3" color="#8A2BE2">Google App Engine!</font>' + \
                            '</strong>')

app = webapp2.WSGIApplication([
    ('/', MainHandler)
], debug=True)

 

O conceito de computação em nuvem em inglês, Cloud Computing, refere-se à utilização da memória e da capacidade de armazenamento e cálculo de computadores e servidores compartilhados e interligados por meio da Internet, seguindo o princípio da computação em grade.

O armazenamento de dados é feito em serviços que poderão ser acessados de qualquer lugar do mundo, a qualquer hora, não havendo necessidade de instalação de programas ou de armazenar dados. O acesso a programas, serviços e arquivos é remoto, através da Internet – daí a alusão à nuvem. O uso desse modelo (ambiente) é mais viável do que o uso de unidades físicas.

SandBox

O SandBox, em português, caixa de areia (onde as crianças brincam e o gato faz caca, nem precisa explicar, não é?), é um ambiente de desenvolvimento utilizado para desenvolvimentos primários, existem vários tipos de ambiente SandBox e geralmente estão associados a uma metodologia de desenvolvimento. Por exemplo, desenvolvimento de grandes aplicações, uma equipe de desenvolvedores podem utilizar o ambiente de SandBox para criar e testar aplicações sem risco de interferir com a configuração do ambiente de desenvolvimento oficial, após a aplicação ser testada ela passa para um ambiente DEV oficial e o ambiente de SandBox é descartado, sendo constantemente atualizado com uma copia do ambiente de desenvolvimento da empresa. Em desenvolvimento para a web, as empresas que permitem programação em seus ambientes, disponibilizam um ambiente de SandBox para que o usuário aprenda a criar aplicações utilizando virtualizações dos seus ambientes de desenvolvimento, porem sem interferir nos mesmos.

Para permitir que o Google App Engine distribua os pedidos para aplicações em vários servidores web, e para evitar uma aplicação de interferir com a outra, o aplicativo é executado em um ambiente de sandboxrestrito.

Google SandBox Python: https://developers.google.com/appengine/docs/python/#Python_The_sandbox

Editor de Código – Python

Você pode utilizar qualquer editor de texto ou IDE para criar suas aplicações Python, recomendamos que para Windows você utilize o editor open source chamado Notepad++ que pode ser baixado clicando aqui.

 

O que você deve saber sobre o Google Cloud

  • O nome da aplicação é chamado de AppID e deve ser único para não haver colisão de nome na web.
  • As boas praticas recomendam criar nomes de aplicação e diretórios utilizando caracteres minúsculos.
  • O servidor web local do Google App Engine é baseado na tecnologia Apache.
  • As portas locais não devem colidir com outras portas em uso por algum servidor web em seu computador.

 

Cloud Google – Criando uma aplicação: Hello World App

Agora que você já sabe os princípios do conceito de programação nas nuvens, vamos criar nosso primeiro programa Cloud, presumimos que você já tenha instalado em seu computador o Google App Engine e a versão do Python 2.7.x.

1- Abra o Google App Engine Launcher, no menu File clique em Create New Application, escolha o nome da aplicação e um diretório para os arquivos de código fonte que serão gerados automaticamente:

AppID

AppID

2 – Dê um duplo clique na sua aplicação, e uma janela o questionara da porta local para o servidor web do App Engine, as portas não devem colidir, escolha uma porta e clique em Update:

Update - Porta

Update – Porta

3 – Com sua aplicação selecionada clique no botão Run e espere até que o ícone da aplicação fique verde:

Run - Ok - verde

Run – Ok – verde

4 – Agora seu servidor web local esta rodando e sua aplicação pode ser testada. Os códigos fontes foram gerados no diretório local que você escolheu quando criou sua aplicação, entre no diretório e abra o arquivo chamado main.py no editor Notepad++:

Notepad++ - Python

Notepad++ – Python

5 – O Google App Engine cria aplicações no modelo MVC, utilize o código abaixo para modificar o código gerado automaticamente, salve e clique no botão Browser, sua aplicação será aberta localmente no seu navegador web:

App - Local

App – Local

6 – Tudo Ok localmente, agora vamos utilizar os servidores Cloud do Google para hospedar nossa aplicação. Você precisa de uma conta do Google, crie caso ainda não tenha, clique no botão Dashbord para criar sua aplicação nos servidores do Google, preencha seu AppID (nome da Aplicação), concorde com os termos de serviço e clique no botão criar:

Dashbord - Google

Dashbord – Google

 

7 – Após criar sua App no ambiente Cloud do Google, clique no botão Deploy para efetuar o Upload do seu programa para as nuvens, forneça o seu e-mail e sua senha para autenticação:

Deploy - Google Cloud

Deploy – Google Cloud

8 – Pronto! Sua App já esta nas nuvens. você pode testar chamando o endereço de sua aplicação no navegador, o endereço é formado pelo AppId mais o caminho do SandBox do Google:

App - Nas Nuvens

App – Nas Nuvens

Exemplo:

Neste programa criamos uma aplicação nas nuvens utilizando a linguagem de programação Python e a tecnologia Cloud dos servidores do Google.

Se você tem uma conta no Google você pode ver esta aplicação clicando aqui:  http://daengineapp01.appspot.com/

Python

main.py

#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import webapp2

class MainHandler(webapp2.RequestHandler):
    def get(self):
        self.response.write('<h1>Desenvolvimento Aberto</h1>' + \
		                    '</br>Hello world!</br>' + \
							'<p><strong>' + \
							'<font size="3" color="#8A2BE2">Google App Engine!</font>' + \
							'</p></strong>')

app = webapp2.WSGIApplication([
    ('/', MainHandler)
], debug=True)

O Google App Engine permite que você construa aplicações web nos mesmos sistemas escaláveis ​​que as aplicações criadas pelo Google.  Os aplicativos App Engine são fáceis de construir, fácil de manter e fácil de escalar. Com o Google App Engine, não há servidores para manter. Se você acabou de fazer upload de seu aplicativo, ele está pronto para servir a seus usuários.

Porque Python ?

Você pode estar se perguntando: Google App Engine também suporta Java e Go, Porque não esses idiomas?”. Para a experiência de aprendizagem mais rápida, Python é a melhor escolha para os novos programadores (é usado para ensinar as crianças como codificar), e também popular com veteranos. Aqui está uma boa explicação para desenvolvedores experientes comparando Python com uma linguagem estaticamente tipada, como C# ou Java ou C++. Ou seja o Google utiliza Python em muitas de suas aplicações e esta apostando nesta linguagem e em futuros desenvolvedores das categorias de base.

Python 2.7.8: https://www.python.org/download

Google App Engine for Python: https://developers.google.com/appengine/downloads#Google_App_Engine_SDK_for_Python

Instalando o Google App Engine

1- Após baixar o arquivo com a extensão MSI, você pode o executar como administrador do sistema, caso você não tenha o Python instalado em seu computador o próprio instalador o ajudara a efetuar a instalação:

Download Python

Download Python

2 – Aceite o termo de licença e clique em next:

Licença

Licença

3 – Escolha o local de instalação e as opções de atalhos do aplicativo, caso mude a instalação você precisa configurar o caminho mais tarde na aba preferencias:

Local da instalação

Local da instalação

4 – Após as opções configuradas clique em instalar:

Instalar

Instalar

5 – Aguarde o progresso da instalação:

Progresso

Progresso

6 – Clique em Finish para concluir a instalação:

Concluir

Concluir

7 – Após a instalação abra o Google App Engine, um aviso será mostrado em um janela dizendo que o sistema não sabe onde encontrar a instalação do Python, você precisa configurar o caminho do executável do Python. No menu Edit, Preferences, inclua os dados na opção Python Path:

Instalação do Python

Instalação do Python

Pronto! agora você precisa fechar e abrir novamente o Google App Engine e já estará apto a criar seu primeiro programa com a tecnologia Cloud.

Como criar minha primeira Aplicação Google nas nuvens?

Para criar sua primeira aplicação nas nuvens utilizando Python e a tecnologia Googleclique aqui.

 

Database – Function – Oracle – Python

Publicado: 31 de julho de 2014 em Python

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

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.

Function - Python

Function – Python

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;

Python

#!/usr/bin/env python
# -*- coding: latin-1 -*-
# Desenvolvimento Aberto
# FunctionOracle.py

# importa modulos
import wx
import wx.grid
import cx_Oracle

# Cria classe generica de uma WX.Grid
# A classe abaixo faz parte da documentação WXPython oficial
# Este trecho de código é util para manipular a grade

class GenericTable(wx.grid.PyGridTableBase):
    def __init__(self, data, rowLabels=None, colLabels=None):
        wx.grid.PyGridTableBase.__init__(self)
        self.data = data
        self.rowLabels = rowLabels
        self.colLabels = colLabels

    def GetNumberRows(self):
        return len(self.data)

    def GetNumberCols(self):
        return len(self.data[0])

    def GetColLabelValue(self, col):
        if self.colLabels:
            return self.colLabels[col]

    def GetRowLabelValue(self, row):
        if self.rowLabels:
            return self.rowLabels[row]

    def IsEmptyCell(self, row, col):
        return False

    def GetValue(self, row, col):
        return self.data[row][col]

    def SetValue(self, row, col, value):
        pass     

# Inicializa Grade
dados = []
colLabels  = []
rowLabels = ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10")

# Cria conexão
def conectarORA():
    sconexao = "user/pa55w0rd@localhost/XE"
    try:
       con = cx_Oracle.connect(sconexao)
    except ValueError:
       tkMessageBox.showinfo(title="Menssagem", message="Erro de Conexão", parent=janela)
    return con

# Executa e retorna SQL
def retornaTabelaORA(sql, con):
     cursor = con.cursor()
     cursor.execute(sql)
     return cursor

def retornaDados(idfunc):
    # Cria conexão
    con = conectarORA()
    # Envia dados a grid

    sql = "Select A.ID_FUNCIONARIO, " + "A.NOME, " + " A.CARGO, " + \
          " A.SALARIO, " + "B.PORCENTAGEM, " + "C.VDESCONTO, " + \
          "C.DATA_LANC,  " + \
          "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  AND " + \
          "A.ID_FUNCIONARIO = " + idfunc
    # retorna set de dados
    tabela = retornaTabelaORA(sql, con)

    # Retorna metadados da tabela
    for i in range(0, len(tabela.description)):
        colLabels.append(tabela.description[i][0])

    # Executa um fecth em todos os registros
    resultado = tabela.fetchall()

    # Popula dados
    for conteudo in resultado:
        dados.append(conteudo)

# Cria classe da grid
class SimpleGrid(wx.grid.Grid):
    def __init__(self, parent):
        wx.grid.Grid.__init__(self, parent, -1, pos=(5,90), size=(850,200))    

# Cria formulario
class TestFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, -1, "Desenvolvimento Aberto - Functions - Python", size=(900, 350))
        panel        = wx.Panel(self, wx.ID_ANY)
        label        = wx.StaticText(panel, -1, label='Oracle Database - Function ->', pos=(300,10))
        lfuncionario = wx.StaticText(panel, -1, label='Cod funcionario:', pos=(20,50))
        self.funcionario  = wx.TextCtrl(panel, size=(100, -1), pos=(120,50))
        lporcentagem = wx.StaticText(panel, -1, label='Porcentagem (%):', pos=(260,50))
        self.porcentagem  = wx.TextCtrl(panel, size=(100, -1), pos=(360,50))
        botao        =   wx.Button(panel, label="Inserir", pos=(480,50))
        botao.Bind(wx.EVT_BUTTON, self.botaoInserir)
        self.grid         = SimpleGrid(panel)

    #Insere dados e dispara trigger
    def botaoInserir(self,event):
        # Conecta e cria um cursor
        con = conectarORA()
        cursor = con.cursor()
        # Insere clausula SQL
        sql = "insert into DESCONTO VALUES (" + self.funcionario.GetValue() + ", " + self.porcentagem.GetValue() + ")";
        # Executa e comita a transação
        cursor.execute(sql)
        con.commit()
        # Retorna set de dados
        retornaDados(self.funcionario.GetValue())
        # Limpa grade
        self.grid.ClearGrid()
        # Insere set de dados contidos em um tuplas
        tableBase = GenericTable(dados, rowLabels, colLabels)
        self.grid.SetTable(tableBase)
        # Atualiza grade
        self.grid.ForceRefresh()

# Inicializa a aplicação
app = wx.PySimpleApp()
frame = TestFrame(None)
frame.Show(True)
app.MainLoop()

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 ServerCreate 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.

Function - C++

Function – C++

Visual Studio

Para efetuar as conexões com os diferentes bancos de dados você precisa primeiro configurar os drivers ODBC necessários no sistema operacional, depois você pode criar um design com 3 componentes RadioButton, 2 componentes Static Texts, 2 componentes Text Control, um componente Button e um componente CListControl,  você encontra um walkthrough de como configurar os drivers ODBC na categoria SQL e C++ deste site, use a figura abaixo para referencia do design:

Visual C++ - Design Time

Visual C++ – Design Time

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

C++

Classe – Arquivo .h

// Classe gerada automaticamente
// AcessocppDlg.h : header file
//

#pragma once

// Inclui classe de banco de dados MFC
#include "afxdb.h"
#include "afxcmn.h"
#include "afxwin.h"

class CAcessocppDlg : public CDialogEx
{

public:
	CAcessocppDlg(CWnd* pParent = NULL);	// standard constructor

	enum { IDD = IDD_ACESSOCPP_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support

protected:
	HICON m_hIcon;

	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:

	// Cria métodos e objetos da classe
	CDatabase db;
	CString bancodedados;
	void conectarDB(CString dns, CString usuario, CString senha);

	afx_msg void OnBnHotItemChangeRadio1(NMHDR *pNMHDR, LRESULT *pResult);
	afx_msg void OnBnHotItemChangeRadio2(NMHDR *pNMHDR, LRESULT *pResult);
	afx_msg void OnBnHotItemChangeRadio3(NMHDR *pNMHDR, LRESULT *pResult);
	afx_msg void OnBnClickedButton1();
	CListCtrl m_tabela;
	CEdit m_funcionario;
	CEdit m_porcentagem;
};

Classe – Arquivo .cpp

// Código gerado automaticamente
// AcessocppDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Acessocpp.h"
#include "AcessocppDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);   

protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()

CAcessocppDlg::CAcessocppDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CAcessocppDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CAcessocppDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST2, m_tabela);
	DDX_Control(pDX, IDC_EDIT1, m_funcionario);
	DDX_Control(pDX, IDC_EDIT2, m_porcentagem);
}

BEGIN_MESSAGE_MAP(CAcessocppDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_NOTIFY(BCN_HOTITEMCHANGE, IDC_RADIO1, &CAcessocppDlg::OnBnHotItemChangeRadio1)
	ON_NOTIFY(BCN_HOTITEMCHANGE, IDC_RADIO2, &CAcessocppDlg::OnBnHotItemChangeRadio2)
	ON_NOTIFY(BCN_HOTITEMCHANGE, IDC_RADIO3, &CAcessocppDlg::OnBnHotItemChangeRadio3)
	ON_BN_CLICKED(IDC_BUTTON1, &CAcessocppDlg::OnBnClickedButton1)
END_MESSAGE_MAP()

BOOL CAcessocppDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	SetIcon(m_hIcon, TRUE);
	SetIcon(m_hIcon, FALSE);		

	// Desenvolvimento Aberto
	// Inicializa dialogo

	// Define variavel padrão para o banco de dados
	bancodedados = "oracle";

	// Cria o modelo de exibição de dados
	m_tabela.SetView(LV_VIEW_DETAILS);
	m_tabela.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES);

	return TRUE;
}

void CAcessocppDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

void CAcessocppDlg::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 CAcessocppDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

// **************************
// * Desenvolvimento Aberto *
// **************************
// Nosso código começa aqui

// Seleciona banco de dados Oracle
void CAcessocppDlg::OnBnHotItemChangeRadio1(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMBCHOTITEM pHotItem = reinterpret_cast<LPNMBCHOTITEM>(pNMHDR);

	bancodedados = "oracle";
	*pResult = 0;
}

// Seleciona banco de dados IBM DB2
void CAcessocppDlg::OnBnHotItemChangeRadio2(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMBCHOTITEM pHotItem = reinterpret_cast<LPNMBCHOTITEM>(pNMHDR);

	bancodedados = "db2";
	*pResult = 0;
}

// Seleciona banco de dados MSSQL
void CAcessocppDlg::OnBnHotItemChangeRadio3(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMBCHOTITEM pHotItem = reinterpret_cast<LPNMBCHOTITEM>(pNMHDR);

	bancodedados = "mssql";
	*pResult = 0;
}

// Evento de clique do botão
void CAcessocppDlg::OnBnClickedButton1()
{
	// campo de dado da tabela
	CString m_campo;

	// Abre conexão
	if (bancodedados == "oracle")
	{
		conectarDB(L"OracleXE", L"daberto", L"p@55w0rd");
	}

	if (bancodedados == "db2")
	{
		conectarDB(L"IBMDB2", L"db2admin", L"p@55w0rd");
	}

	if (bancodedados == "mssql")
	{
		conectarDB(L"MSSQLSERVER", L"devaberto", L"p@55w0rd");
	}

	// Cria um set de dados
	CRecordset  dados(&db);

	// Cria variáveis de entrada
	CString m_func;
	CString m_porc;

	// Recupera valor de entrada
	m_funcionario.GetWindowTextW(m_func);
	m_porcentagem.GetWindowTextW(m_porc);

	// Cria instrução SQL para disparar a trigger
	CString sqltrigger = L"insert into DESCONTO VALUES (" + m_func + ", " + m_porc + ")";

	// Executa instrução SQL
    db.ExecuteSQL(sqltrigger);

	// Cria proprietario do banco de dados
	CString owner = L"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
	CString sql = CString("Select A.ID_FUNCIONARIO, A.NOME, A.CARGO, ")
				+ CString(" A.SALARIO, B.PORCENTAGEM,C.VDESCONTO, ")
				+ CString("C.DATA_LANC,  ") + owner
				// Executa função SLIQUIDO - retorna o calculo do salario liquido.
				+ CString("SLIQUIDO(A.SALARIO, C.VDESCONTO) AS SLIQUIDO ")
				+ CString("from FUNCIONARIOS A, DESCONTO B, SALARIO C Where ")
				+ CString("A.ID_FUNCIONARIO = B.ID_FUNCIONARIO  AND ")
				+ CString("A.ID_FUNCIONARIO = C.ID_FUNCIONARIO ")
				+ CString("Order by 1 desc");

	// Abre set de dados
	dados.Open(CRecordset::forwardOnly, sql);

	// Cria item
	LVITEM lvItem;

	// cria estrutura para inserir o item
	typedef struct _LVITEM
	{
		UINT mask;
		int iItem;
		int iSubItem;
		UINT state;
		UINT stateMask;
		LPTSTR pszText;
		int cchTextMax;
		int iImage;
		LPARAM lParam;
        #if (_WIN32_IE >= 0x0300)
		  int iIndent;
        #endif
	 } LVITEM, FAR *LPLVITEM;

	// Define variaveis de itens
	int InsertItem(const LVITEM* pItem);
	int nItem;

	// Converte CString para LPTSTR atraves de um TCHAR
	TCHAR sz[1024];

	// Verifica colunas
	short nFields = dados.GetODBCFieldCount();
	int colunas = m_tabela.GetHeaderCtrl()->GetItemCount();

	// Verifica colunas
	if (colunas == 0)
	{
		// Lê metadata da tabela
		CODBCFieldInfo field;
		for (UINT i = 0; i < nFields; i ++)
		{
			dados.GetODBCFieldInfo(i, field);
			m_tabela.InsertColumn(i, field.m_strName, LVCFMT_LEFT, 100);
		}

	}

	// Deleta itens do controle de lista
	m_tabela.DeleteAllItems();

	// Recupera dados da tabela
	while (!dados.IsEOF())
	{
		for (short index = 0; index < nFields; index++)
		{
			dados.GetFieldValue(index, m_campo);

			// Retorna linha do banco de dados
			if (index == 0)
			{
				// Insere linha
				lvItem.mask = LVIF_TEXT;
				lvItem.iItem = 0;
				lvItem.iSubItem = 0;
				lvItem.pszText = lstrcpy(sz, m_campo);
				nItem = m_tabela.InsertItem(&lvItem);
			}

			// Retorna colunas da linha
			m_tabela.SetItemText(nItem, index, lstrcpy(sz, m_campo));

		}
		// Move o cursor para a proxima linha
		dados.MoveNext();
	}

	// Fecha o set de dados e a conexão
	dados.Close();
	db.Close();

}

void CAcessocppDlg::conectarDB(CString dns, CString usuario, CString senha)
{
	// 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);
}

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 ServerCreate 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.

Function  - C#

Function – C#

Visual Studio

Para efetuar as conexões com os diferentes bancos de dados você precisa primeiro configurar seu projeto com os assemblers ADO.NET  necessários e depois você pode criar um design com 3 componentes RadioButton, 2 componentes Labels, 2 componentes TextBoxes e um componente Button e um componente DataGridView use a figura abaixo para referencia:

Function - Design Time

Function – Design Time

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

C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient; 
using Oracle.DataAccess.Client; 
using IBM.Data.DB2; 


namespace Acesso
{
    public partial class Dados : Form
    {
        private static OracleConnection connORA; // ODAC 12c
        private static DB2Connection connDB2;   // IBM Data Server Provider
        private static SqlConnection connMSSQL; // ADO .NET
        
        DataTable dataTable;

        string sql;
        static string bancodedados;

        public Dados()
        {
            InitializeComponent();
        }

        // Cria métodos de conexão 
        // Você pode optar por um unico método se usar apenas ADO.NET
        // Neste caso usamos os drivers nativos de conexão de cada banco de dados.
        // Todos os drivers são baseados em ADO .NET
        public void conexaoODAC(string Username, string Password, string Datasource)
        {
            try
            {
                // String de Conexao
                string connectionString =

                    // Usuario
                    "User Id=" + Username +

                    // Senha
                    ";Password=" + Password +

                    // TNSnames
                    ";Data Source=" + Datasource;

                //Conecta ao datasource usando a conexão Oracle
                 connORA = new OracleConnection(connectionString);

                //Abre a conexão com o banco de dados
                connORA.Open();
               

            }
            // Retorna erro
            catch (Exception ex)
            {
                // Mostra menssagem de erro
                MessageBox.Show(ex.ToString());

            }
        }
 
        void conexaoDB2(string Server, string Database,
                                    string Username, string Password, string Timeout)
        {
            try
            {
                // String de Conexao
                string connectionString =
 
                    // Servidor
                    "Server=" + Server +
 
                    // Banco de dados
                    ";Database=" + Database +
 
                    // Usuario
                    ";UID=" + Username +
 
                    // Senha
                    ";PWD=" + Password +
 
                    // TNSnames
                    ";Connect Timeout=" + Timeout;
 
                //Conecta ao datasource usando a conexão DB2
                connDB2 = new DB2Connection(connectionString);
 
                //Abre a conexão com o banco de dados
                connDB2.Open();                
 
            }
            // Retorna erro
            catch (Exception ex)
            {
                // Mostra menssagem de erro
                MessageBox.Show(ex.ToString());
 
            }
        }

         public void conexaoMSSQL(string Server, string Database,
                                     string Username, string Password, string Timeout)
         {
             try
             {
                 // String de Conexao
                 string connectionString =

                     // Servidor
                     "Data Source=" + Server +

                     // Banco de dados
                     ";Initial Catalog=" + Database +

                     // Usuario
                     ";User ID =" + Username +

                     // Senha
                     ";Password=" + Password +

                     // TNSnames
                     ";Connect Timeout=" + Timeout;

                 //Conecta ao datasource usando a conexão Padrão
                 connMSSQL = new SqlConnection(connectionString);

                 //Abre a conexão com o banco de dados
                 connMSSQL.Open();
                 

             }
             // Retorna erro
             catch (Exception ex)
             {
                 // Mostra menssagem de erro
                 MessageBox.Show(ex.ToString());

             }
         }

        // Retorna um set de dados
         public  DataTable retornaTabela(string sql, string sqlTrigger)
         {
             // Declara comandos para Stored Procedure
             OracleCommand cmdORA;
             DB2Command cmdDB2;
             SqlCommand cmdSQL;
             
             // Cria instância da classe
             Dados acesso = new Dados();

             // Define banco de dados

             if (bancodedados == "oracle")
             {                 
                 // Efetua Login no banco de dados
                 acesso.conexaoODAC("daberto", "p@55w0rd", "XE");

                 // Define a instrução SQL e a conexão
                 cmdORA = new OracleCommand(sqlTrigger, connORA);
                 
                 // Executa query
                 cmdORA.ExecuteNonQuery();

                 // Cria comandos para retornar dados para exibir a grade de dados
                 OracleCommand oracmd = new OracleCommand(sql, connORA);
                 OracleDataReader orareader = oracmd.ExecuteReader();
                 dataTable = new DataTable();
                 dataTable.Load(orareader);
             }
             
             if (bancodedados == "db2")
             {
                 acesso.conexaoDB2("localhost", "DEVA", "db2admin", "p@55w0rd", "40");

                 cmdDB2 = new DB2Command(sqlTrigger, connDB2);
                                  
                 cmdDB2.ExecuteNonQuery();

                 DB2Command db2cmd = new DB2Command(sql);
                 db2cmd.Connection = connDB2;
                 DB2DataReader db2reader = db2cmd.ExecuteReader();
                 dataTable = new DataTable();
                 dataTable.Load(db2reader);                
             
             }
             
             if (bancodedados == "mssql")
             {
                 acesso.conexaoMSSQL("localhost", "DevAberto", "devaberto", "p@55w0rd", "");

                 cmdSQL = new SqlCommand(sqlTrigger, connMSSQL);
                 
                 cmdSQL.ExecuteNonQuery();

                 SqlCommand mssqlcmd = new SqlCommand(sql);
                 mssqlcmd.Connection = connMSSQL;
                 SqlDataReader mssqlreader = mssqlcmd.ExecuteReader();
                 dataTable = new DataTable();
                 dataTable.Load(mssqlreader);
             
             }

             return  dataTable;
         }
                  
        // configura programa
        private void Form1_Shown(object sender, EventArgs e)
        {
            radioButton1.Checked = true;
            bancodedados = "oracle";
        }

        // Conecta dados
        private void button1_Click(object sender, EventArgs e)
        {
            // Cria instância da classe
            Dados dados = new Dados();

            // Insere Porcentagem de desconto e executa trigger
            string sqltrigger = "insert into DESCONTO VALUES (" + textBox1.Text +
                              ", " + textBox2.Text + ")";

            // 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";

            // Alimenta grid de dados
            dataGridView1.DataSource = dados.retornaTabela(sql, sqltrigger);
           
        }

        // Seleciona banco de dados Oracle
        private void radioButton1_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButton1.Checked)
            {
                bancodedados = "oracle";
            }

        }

        // Seleciona banco de dados IBM DB2
        private void radioButton2_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButton2.Checked)
            {
                bancodedados = "db2";
            }
        }

        // Seleciona banco de dados MSSQL Server
        private void radioButton3_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButton3.Checked)
            {
                bancodedados = "mssql";
            }
        }        
    }
}

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 ServerCreate 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.

Triggers - Oracle - DB2 - MSSQL

Functions – Oracle – DB2 – MSSQL

 

 

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();

			}
		});
	}
}

Programas Include permitem que você gerencie programas complexos de uma forma ordenada. Os grupos funcionais e módulo usam programas Include para armazenar as partes do programa que pertencem um ao outro. O ABAP Workbench o apoia extensivamente ao criar tais programas complexos, criando os programas Includes automaticamente, atribuindo-lhes nomes exclusivos.

Os Includes permitem que você use o mesmo código fonte em diferentes programas. Por exemplo, isso pode ser útil se você tiver declarações de dados longas que você deseja usar em programas diferentes. Você pode por exemplo utilizar programas Includes para criar uma biblioteca de classes locais, eventos PBO, eventos PAI, procedimentos Forms entre outros, ou quando você queira organizar melhor seu código fonte.

Entretanto os programas Includes possuem duas restrições:  programas Includes não podem chamar a si mesmo e devem conter declarações completas, deste modo não é possível separar em programas Includes a definição de uma classe de sua implementação em arquivos de código fonte diferentes, assim como é de boa pratica em C++, já que ABAP OO foi baseado nesta linguagem, principalmente explicitando deste modo a separação da sintaxe entre a definição de uma classe e a implementação. Mas deveria, certo?

Tipo I - Programa Include

Tipo I – Programa Include

Os Includes são programas do tipo I – são um meio de dividir o código do programa em unidades menores e mais manejáveis. É possível inserir a codificação de um programa Include, em qualquer ponto de outro programa ABAP usando a instrução Include. Não há nenhuma relação técnica entre programas Includes e blocos de processamento. Includes são mais adequados para as unidades de programação lógicas, tais como declarações de dados ou conjuntos de blocos de processamento similares.

Exemplo:

Neste exemplo criamos um programa ABAP comum chamado ZMEUINCLUDE e um programa do tipo I, chamado ZINC_DEF, onde o programa include contem uma classe e o programa principal chama seu método estaticamente.

Abap

Programa – Principal

*&---------------------------------------------------------------------*
*& Report  ZMEUINCLUDE
*&
*&---------------------------------------------------------------------*
*& Desenvolvimento Aberto
*& Include - Modularization Techniques
*&---------------------------------------------------------------------*

REPORT  ZMEUINCLUDE.

* Chama o programa include
INCLUDE ZINC_DEF.

START-OF-SELECTION.
* Instancia estatica do objeto
HELLO=>OLA( ).

Programa – Include

*&---------------------------------------------------------------------*
*& Desenvolvimento Aberto
*&---------------------------------------------------------------------*
*& Include: ZINC_DEF
*&---------------------------------------------------------------------*

* Definição da classe
CLASS hello DEFINITION.

  PUBLIC SECTION.

    CLASS-METHODS Ola.

ENDCLASS.

* Implementação da classe
CLASS hello IMPLEMENTATION.

  METHOD ola.
    Write  'Hello World Include'.
  ENDMETHOD.

ENDCLASS.

SAP – Submit – Calling Programs – Abap

Publicado: 27 de julho de 2014 em Abap

Se você precisa programar uma aplicação extensiva, um único programa pode se tornar muito complexo. Para tornar o programa mais fácil de ler, muitas vezes é razoável dividir as funções necessárias entre vários programas. Programas ABAP, como grupos de funções, também podem se conectar com outros programas ABAP e podem se comunicar de varias maneiras diferentes.

A instrução Submit permite que você possa especificar o nome do programa que você deseja chamar estaticamente, digitando o nome do programa no código do programa de chamada, ou dinamicamente, especificando o nome de um campo (entre parênteses) que contém o nome do programa. Se o sistema não encontrar o programa executável especificado ao tentar executar a instrução, ocorre um erro de execução.

O Submit possui a instrução complementar chamada And Return que permite retornar ao programa que o chamou, deste modo o sistema armazena os dados do programa executável chamado e retorna para a chamada após o processamento do programa chamado. O sistema retoma a execução do programa de chamada para a declaração após a chamada.

Submit

Submit

Uma observação interessante neste ponto é que cada vez que você executa um programa executável, uma declaração SUBMIT ocorre. Quando você digita o nome do programa em uma transação como SE38 e SA38 e escolhe Executaruma declaração Submit ocorre na transação. É, portanto, um atributo técnico de um programa do tipo 1 que são chamados usando a instrução Submit, embora sua principal característica do ponto de vista de um usuário é que eles são iniciados em primeiro plano.

Exemplo:

Neste exemplo criamos dois programas, o ZPROG1 e ZPROG2, onde o programa 1 chama e alimenta parâmetros para o programa 2 e assim que o programa 2 é fechado, a execução do programa 1 é automaticamente retomada.

Abap

Programa – 1

*&---------------------------------------------------------------------*
*& Report  ZPROG1
*&
*&---------------------------------------------------------------------*
*& Desenvolvimento Aberto
*& Programa 1 - Call Program
*&---------------------------------------------------------------------*

REPORT  ZPROG1.

Write : / 'Eu sou o programa 1'.

* Chama e transfere dados
SUBMIT ZPROG2 VIA SELECTION-SCREEN
              WITH v1 eq 'Desenvolvimento'
              WITH v2 eq 'Aberto' AND RETURN.

SKIP 2.

FORMAT HOTSPOT COLOR 3 INVERSE ON.
Write : / 'Você retornou para o programa 1'.

Programa – 2

*&---------------------------------------------------------------------*
*& Report  ZPROG2
*&
*&---------------------------------------------------------------------*
*& Desenvolvimento Aberto
*& Programa 2 - Call Program
*&---------------------------------------------------------------------*

REPORT  ZPROG2.

PARAMETER : v1(15) TYPE c,
            v2(15) TYPE c.

START-OF-SELECTION.

WRITE : 'Eu sou o Programa 2 e recebi duas variáveis', /,
      / 'Variável 1 = ', v1,
      / 'Variável 2 = ', v2.

SKIP.

FORMAT HOTSPOT COLOR 6 INVERSE ON.
WRITE : / 'Clique no botão Voltar e em Fechar para retornar ao programa 1'.

SAP – Transaction Codes – TCodes – Abap

Publicado: 26 de julho de 2014 em Abap

Cada função no sistema SAP tem um código de transação associado. Um código de transação consiste em letras, números, ou ambos. Você pode entrar com um código de transação no campo de comando quando desejar ir para qualquer tarefa em um aplicativo SAP mais rápido. Ao entrar um código de transação em vez de usar o menu, você vai para uma tarefa e começa a função em uma única etapa.

Podemos dizer que Transaction Codes ou Tcodes são como atalhos em um sistema SAP, você pode digita-los e acessar diretamente o conteúdo que você necessita, como programas entre outros tipos de transações, você também pode criar um código de transação para executar seus programas.

Mais informações sobre Tcodes: Maintaining Transactions e Working with Transaction Codes

Criando um código de transação para seu programa

1 – Primeiro precisamos criar um programa para ser executado pelo nosso tcode, entre na transação SE38 e digite o código abaixo, logo após criar, testar e ativar o programa, entre na transação SE93 e digite para nosso Tcode o seguinte código: ZDA1

SE93 - Maintaining Transactions

SE93 – Maintaining Transactions

2 – Após a criar o Tcode você precisa escolher o tipo de transação desejada, existem vários tipos, escolha a opção Program and Selection Screen:

Create Transaction

Create Transaction

3 – Preencha os detalhes da sua transação, como o pacote que será inserida, descrição, autorização, o tipo de suporte para o SAP GUI e o nome do programa que você deseja executar, em nosso caso ZTCODE:

Change Report Transaction

Change Report Transaction

4 – Após salvar sua transação, digite /n para voltar para a tela inicial do sistema e digite, ZDA1 no campo do Tcode e aperte a tecla Enter:

SAP Easy Access

SAP Easy Access

5 – Então seu programa será executado com sucesso:

ZDA1 - Programa

ZDA1 – Programa

Exemplo:

Neste exemplo criamos um programa chamado ZTCODE e o associamos a uma transação de nome ZDA1.

Abap

*&---------------------------------------------------------------------*
*& Report  ZTCODE
*&
*&---------------------------------------------------------------------*
*& Desenvolvimento Aberto
*& Minha primeira transação - Tcode
*&---------------------------------------------------------------------*

REPORT  ZTCODE.

Write : / 'Hello World - Tcode', /.
skip 2.
Write at 50 :  'ZDA1 - transação para este programa' color 2.