viernes, 30 de mayo de 2014

ABC con jQuery, Ajax, PHP

#CRUD #ABC #jQuery #Ajax #PHP

En esta ocasión, les dejo un artículo dedicado a construir un completo ABC (Altas, Bajas y Cambios) o CRUD, sobre una tabla MySQL, mediante el uso de las herramientas:

  • PHP
  • jQuery
  • Ajax

Tratamos de hacer todo, desde cero, esto que indica, que no trabajamos con ningún plugin de jQuery, sino que todo lo hicimos a mano. ¿Porqué hacerlo así? En algunas ocasiones, tenemos un buen plugin de jQuery que hace algo, pero queremos además agregarle una funcionalidad extra, por ejemplo, tenemos un plugin que valida un formulario, pero queremos que haga el envío de los datos mediante ajax y de esa forma, actualice la tabla en MySQL (ya sea para borrar, actualizar o agregar un registro), pero sin recargar el sitio en el que estamos.

Para tal motivo, iniciamos con este artículo, tratamos de dejarlo lo más completo posible, además agregamos funcionalidades tales como refrescar la información y dar clic a una tabla y abrir la "ventana" de actualización.

Por todo lo anteriormente mencionado, creamos este Tutorial dedicado a los que están comenzando o quieren ver nuevas opciones con jQuery.

 
 

Aclaración

 
Antes de iniciar, vamos hacer algunas aclaraciones:

  • Las acciones de agregar/actualizar,consultar y borrar, se harán desde archivos separados, para esto creamos cada archivo según la necesidad, en el caso de Agregar/Actualizar, en un único archivo se procesan las dos acciones.
  • La tabla donde se muestran los registros se cargará dinámicamente, por lo tanto se debe crear el archivo de consulta (llamado getdata.php).
  • El archivo modificar.php, muestra el formulario desde donde se llama las acciones de actualizar/agregar y borrar.
  • El archivo conex.php contiene las instrucciones de conexión a la base de datos, se debe adecuar al hosting donde se vaya a ejecutar.
 

Desarrollo

Estructura de la tabla utilizada


CREATE TABLE `tmp_usuarios` (
  `user` varchar(20) NOT NULL,
  `pass` varchar(20) NOT NULL,
  `correo` text NOT NULL,
  `estado` tinyint(1) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8

Contenido de Archivos PHP

getdata.php


<?php
/*Contenido del archivo getdata.php
el cual construye la tabla en html que mostrará los datos de los usuarios
a partir de la tabla tmp_usuarios
*/
include('conex.php');
 
$sql = "Select * from tmp_usuarios" ;
$resUser = mysql_query($sql, $conex) or die(mysql_error());
$totUser = mysql_num_rows($resUser);
 
if ($totUser> 0) {
 
$tabla  = '<table width="100%" border="1" id="tblUser">';
$tabla .= '<tr>';
$tabla .= '   <th scope="col">Usuario</th>';
$tabla .= '   <th scope="col">Clave</th>';
$tabla .= '   <th scope="col">Correo</th>';
$tabla .= '  </tr>';
 
   while ($rowUser = mysql_fetch_assoc($resUser)) {
    $tabla .= '  <tr>';
    $tabla .= '    <td>' . $rowUser["user"]. '</td>';
    $tabla .= '    <td>' . $rowUser["pass"]. '</td>';
    $tabla .= '    <td>' . $rowUser["correo"]. '</td>';
    $tabla .= '   </tr>';
   }
   $tabla .= ' </table>';   
   echo $tabla;
}else{
    echo "NO hay Información que mostrar";
    }
 
?>

deluser.php


<?php
/*Contenido archivo deluser.php*/
include('conex.php');
 
$user  = $_POST["nombre"];
 
if(empty($user)) {
    echo "0";
    return false;
}
$sql = "Delete from tmp_usuarios where user='" . $user ."'" ;
 
mysql_query($sql, $conex) or die(mysql_error());
echo "1";
?>

saveuser.php


<?php
/*
Contenido del archivo saveuser.php
Se procesa el actualizar (update) y el Insertar (Insert)
*/
include('conex.php');
 
$user  = $_POST["nombre"];
$pass  = $_POST["password"];
$email = $_POST["email"];
 
/*Validamos si el Usuario ya existe, de existir, se actualiza, sino se Ingresa*/
$sql = "Select user from tmp_usuarios where user='" . $user . "'" ;
$resUser = mysql_query($sql, $conex) or die(mysql_error());
$totUser = mysql_num_rows($resUser);
 
if($totUser>0) //Registro ya existe se actualiza
{
    $sql = "Update tmp_usuarios set pass='". $pass."',correo='". $email ."' where user='" . $user . "'";
}else{
    //Registro nuevo, se ingresa
    $sql = "Insert Into tmp_usuarios(user,pass,correo,estado) values ('" . $user ."','" . $pass ."','" . $email ."',0)" ;
}
mysql_query($sql, $conex) or die(mysql_error());
echo "1";
 
?>

Lado del Cliente

Para iniciar, lo primero que debemos hacer es agregar la librería de jQuery, para esto se recomienda siempre tener la última versión. Para agregarla, tomamos el archivo index.php y en la sección head, se agregó:

<script type="text/javascript" src="/js/jquery-1.7.1.min.js"></script>

Mostrar Datos

Una vez que cargamos la librería ya podemos comenzar a trabjar con jQuery. Como vimos, el archivo getdata.php imprime en pantalla la tabla, de tal forma, cada vez que lo mandamos a llamar, se generará la tabla de contenido. Dicha tabla, la tendremos dentro de un div, al cual podremos el id Usuarios, de la siguiente forma

<div id="Usuarios">
<?php include("getdata.php"); ?>
</div>

Podemos observar que incluimos el archivo getdata.php, el cual devuelve la tabla con el resultado de la consulta de la tabla.

Refrescar Datos

Y para el botón refrescar, tenemos

//Botón Refrescar Presionado
$("#refrescar").click(function(){
    $("#Usuarios").html("");
    $("#Usuarios").load("getdata.php", function(){});
    })

Agregar / Modificar Registros

El efecto que se logra, para que muestre el formulario visible de esa forma (un div superpuesto, se logra) con el siguiente estilo

.div_User{
    position: absolute;
    top: 25%;
    left: 25%;
    width: 50%;
    height: 60%;
    padding: 16px;
    background: #fff;
    color: #333;
    z-index:1002;
    overflow: auto;
}

Y, se ubicará en el div

<div class="div_User" id="div_User">

Y es en este div que cargaremos el contenido del formulario. Dicha acción se lleva a cabo de dos formas, dando clic en el botón Agregar o en algún usuario (de haber registros). En el caso del clic del botón,
$("#adduser").click(function(){
       $("#div_User").fadeIn();
       $("#div_User").html("<div id='cargando' style='display:none; color: green;text-align:center' width='100%' height='100%'><img width='16' height='16' src='img/ajax-loader.gif' /> Cargando...</b></div>");
       $("#cargando").css("margin-left", "auto");
       $("#cargando").css("margin-right", "auto");
       $("#cargando").css("display", "inline");
       $("#div_User").load("modificar.php", function(){
           $("#cargando").css("display", "none");
     });
    });

Antes de cargar el archivo modificar.php, ponemos el mensaje de cargando, luego usamos el método load y mandamos a cargamos el archivo modificar.php, si carga bien, se "oculta" el div cargando. Para capturar el clic en la tabla de usuarios, usamos el método live y preguntamos por el evento click

modificar.php

Dentro del archivo modificar.php, veremos que al inicio recibe los valores pasados, si no recibe nada, las variables estarán vacías, el contenido de esas variables, se pone en el value de cada input.

<?php
$user  = $_POST["user"];
$pass  = $_POST["pass"];
$email = $_POST["mail"];
 
?>
 
<form class='contacto' method='POST' action='' id="formu">
            <div><label>Usuario (*):</label><input type='text' class='nombre' name='nombre' id='usuario' value='<?php echo $user;?>'></div>
            <div><label>PassWord (*):</label><input class='nombre' name='password'  id='password' value='<?php echo $pass; ?>' type="password"></div>            
            <div><label>Tu Email (*):</label><input type='text' class='email' name='email'  id='email' value='<?php echo $email; ?>'></div>
            <div><input type='submit' value='Guardar' class='boton' name='boton' id="enviar">
            <?php if(!empty($user)) {?>
            <input type='button' value='Borrar' class='boton' name='boton' id="Borrar">
            <?php }?>
            <input  type='button' value='Cerrar' class='boton' name='boton' id="Cerrar">
            </div>
</form>

Botón Enviar Datos (Actualizar o Modificar

En el evento clic del botón enviar, primeramente usamos preventDefault(), para evitar que se ejecute el Submit del formulario. Luego para cada input preguntamos por el valor y si está vacío, se agrega un spam con la clase error, al final de cada validación, se usa el return false, para evitar que siga a la siguiente instrucción.

Luego de validar todo, utilizamos ajax para enviar los datos al archivo saveuser.php, para capturar los valores del formulario, se utiliza el método serialize de jQuery.

En el ajax, se pone el especifica el tipo (en nuestro caso POST), en url, se especifica el destino (saveuser.php), si sucede algún error (como que no exista el archivo especificado en url), está la sección error:, en data ponemos los valores serializados del formulario.

Si el envío es satisfactorio, se utiliza la sección success, la variable data, contiene lo que envíe de respuesta el archivo saveuser.php, para esto, utilizamos el echo "1", si data contiene el valor 1, se asume que todo salió bien, así que se procede a "repintar" la tabla de usuarios.

/*Evento Click Botón Enviar*/
 $("#enviar").click(function(evento){
     evento.preventDefault(); //Evitamos que el formulario se vaya
 
     /*Validación*/
     var emailreg = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;   //Creamos las reglas para validar el correo
     $(".error").fadeOut().remove();
 
     if ($("#usuario").val() == "") { 
        //alert("Usuario Inválido");
        $("#usuario").focus().after('<span class="error">Usuario Inválido</span>');
        return false;
     }
 
     if ($("#password").val() == "") { 
        //alert("Password Requerido");
        $("#password").focus().after('<span class="error">Password Requerido</span>');
        return false;
     }
 
    if ($("#email").val() == "" || !emailreg.test($("#email").val())) {
        //alert("Dirección de Correo Inválida");
        $("#email").focus().after('<span class="error">E-Mail Inválido</span>');
        return false;       
    }
    /*Fin Validación*/
 
    //Determinanos los datos del formulario y los serializamos
    var datos = $("#formu").serialize();
    //alert(datos);
    // Enviamos el formulario usando AJAX
        $.ajax({
            type: 'POST',
            url: 'saveuser.php',
            error: function(data){
                //Si sucedió algo, se notifica
                    $(".result_fail").fadeIn();
                    $(".result_fail").html("Error Procesando Datos");
                },
            data: datos,
            // Mostramos un mensaje con la respuesta de PHP
            success: function(data) {
                if(data==1){
 
                    /*Reconstruimos la tabla*/
                    $("#Usuarios").html("");
                    $("#Usuarios").load("getdata.php", function(){});
                    /*Fin Reconstruir la tabla*/
 
                    $("#div_User").hide();
                }
                else{
                    $(".result_fail").fadeIn();
                    $(".result_fail").html("Error " . data);
                    return false;
                    }
             }
        });
});
 /*Fin Evento Click Botón Enviar*/

Botón Borrar

De la misma forma, sucede con el botón borrar.

/*Evento Click Botón Borrar*/
$("#Borrar").click(function(){
 
    /*Confirmar si se desea borrar el registro*/
    var Resp = confirm("Eliminar Registro para " + $("#usuario").val());
 
    if(Resp){
            /*Escogió opción ACEPTAR*/
            //Determinanos los datos del formulario y los serializamos
           var datos = $("#formu").serialize();
           // Enviamos el formulario usando AJAX
           $.ajax({
               type: 'POST',
               url: 'deluser.php',
               error: function(data){
                   //Si sucedió algo, se notifica
                       $(".result_fail").fadeIn();
                       $(".result_fail").html("Error Eliminando Registro");
                   },
               data: datos,
               // Mostramos un mensaje con la respuesta de PHP
               success: function(data) {
                   if(data==1){
 
                       /*Reconstruimos la tabla*/
                       $("#Usuarios").html("");
                       $("#Usuarios").load("getdata.php", function(){});
                       /*Fin Reconstruir la tabla*/
 
                       $("#div_User").hide();
                   }
                   else{
                       $(".result_fail").fadeIn();
                       $(".result_fail").html("Error " . data);
                       return false;
                       }
                }
           });      
        }
 
    })
 /*Fin Evento Click Botón Borrar*/

Conclusiones

Espero que este tutorial les sea de mucha utilidad, es bastante básico, pero traté que quedara lo más completo posible. Sígannos en Twitter (o Facebook), para descargar los fuentes, sólo deben compartir este contenido en alguna de las redes sociales que se indica en el botón siguiente e inmediatamente saldrá el link de descarga.  La aplicación pedirá permiso para poder postear.


Hay detalles concernientes a la seguridad, pero este pequeño tutorial les sea de utilidad.

Enlace Relacionado

Tutorial ABC con jQuery y MySQL

"Enseñar es la mejor forma de aprender"


jueves, 29 de mayo de 2014

Poner Larry de Twitter a Volar en tu Web o Blog


#Larry #Twitter #Fly #Web #Blog #Social #Script #Gadget

¿Te gustaría poner en tu Blog o Web a Larry? Es muy sencillo con este script o gadget, será sólo cosa de copiarlo, personalizarlo y listo.



 <script src="http://plantillasgratis.comuv.com/disemucho/pajaro_twitter_navidad/twitter/disemucho.js" type="text/javascript">
</script><script type="text/javascript">
//<![CDATA[
        var birdSprite='http://u.jimdo.com/www21/o/s4e9df44a0ad8ccd8/img/iffeafe7e991f963f/1341590653/std/image.png';
        var targetElems=new Array('img','hr','table','td','div','input','textarea','button',
'select','ul','ol','li','h1','h2','h3','h4','p','code','object','a','b','strong','span');
        var twitterAccount = 'http://twitter.com/#!/tu usuario';
        var twitterThisText ='Sigueme en Twitter';
        tripleflapInit();
//]]>
</script> 

Y listo, vas a tu web y pegas este código o desde blog, ve al diseño y das clic en agregar gadget, escoges el HTML/JavaScript y ahí pegas el script anterior.  Ten en cuenta que debes poner tu usuario (donde lo indica)

Espero te sea de utilidad

"Enseñar es la mejor forma de aprender"

martes, 27 de mayo de 2014

Botón Imprimir - jQuery Plugin


Introducción


jQuery printing plugin es un plugin muy bueno con el que se puede agregar la opción de imprimir a nuestras aplicaciones web.
La forma de funcionar es bastante sencilla, basta con tener un botón, que le pongamos ya sea un class o un id. Dicho botón, puede ser algo con un plugin o un simple enlace, al que le ponemos:

<a href="https://www.blogger.com/iframe.html" id="btnPrint">Print!</a>

Lo que si debemos notar, que se le pasa en el href del enlace, la ruta del archivo a imprimir que bien puede ser un html o algu en php que querramos procesar, para formatear y esas cosas.
Luego el uso es sencillo.

$("#btnPrint").printPage()
Y listo, también podemos mejorarlo con parámetros más "avanzados":


$("#imprimir").printPage(
{
  url: "opciones/opc_suc_set.php",
  attr: "href",
  message:"Su documento está siendo generado"
}
);

Enlaces relacionados

Demo
Descarga

Enseñar es la mejor forma de aprender

lunes, 26 de mayo de 2014

Common Table Expression - SQL Server



Una CTE (Common Table Expression - Expresión de Tabla Común), se puede considerar un conjunto de resultados temporal que se define en el ámbito de la ejecución de una instrucción única SELECT, INSERT, UPDATE, DELETE o CREATE VIEW. Una CTE es similar a una tabla derivada en que no se almacena como un objeto y dura sólo el tiempo que dura la consulta. A diferencia de una tabla derivada, una CTE puede hacer referencia a sí misma y se puede hacer referencia a ella varias veces en la misma consulta.

Al igual que una TVF nos ayuda entre otras cosas a simplificar las consultas grandes, teniendo una mejor visión de la consulta entera.  Las CTE's, también cumplen este objetivo, pero su tiempo de vida es mucho más corto, ya que no se guarda como un objeto de la base de datos, sino que dura el ámbito de la ejecución de la instrucción, la cual puede estar contenida en un SP (Store Procedure) o una consulta general.

En mi caso, ¿dónde las he utilizado? Cuando debo hacer una consulta bastante extensa, que requiere que filtre información sobre datos ya filtrados, básicamente implementando recursividad o reutilizando la consulta anterior. Para los que han programado con Visual FoxPro, es equivalente al manejo de Cursores, con los cuales, la información se obtenía en una consulta (Cursor) y luego ese cursor se podía filtrar y/o utilizar para otra operación.

El uso de una CTE ofrece las ventajas de una legibilidad mejorada y la facilidad de mantenimiento de consultas complejas. La consulta se puede dividir en bloques de construcción lógicos simples e independientes. Estos bloques simples se pueden usar para crear CTE provisionales más complejas hasta que se genere el conjunto de resultados finales.

Las CTE se pueden definir en rutinas definidas por el usuario, como funciones, procedimientos almacenados, desencadenadores o vistas.

Sintaxis


WITH expression_name [ ( column_name [,...n] ) ]
AS
( CTE_query_definition )
 
Al importante que debo destacar es la utilización de un punto y coma (;) al inicio del CTE, ya que SQL Server enviará un error indicando que la última consulta anterior al CTE debe terminar con ;

También se pueden anidar CTE, con la siguiente sintaxis.

;With C1 AS
(
 Select ...
 From T1 
 Where ...
),
C2 AS
(
 Select ...
 From C1 
 Where ...
)
Select ...
  From C2
Where ...;

Ejemplos

En el siguiente ejemplo se muestra el número total de pedidos de venta por año para cada representante de ventas en Adventure Works Cycles:

;WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear)
AS
(
    SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYear
    FROM Sales.SalesOrderHeader
    WHERE SalesPersonID IS NOT NULL
)
SELECT SalesPersonID, COUNT(SalesOrderID) AS TotalSales, SalesYear
FROM Sales_CTE
GROUP BY SalesYear, SalesPersonID
ORDER BY SalesPersonID, SalesYear;

Más ejemplos por parte de Microsoft, pueden tener en este link.

Un ejemplo práctico, es este SP que realice a inicio del 2014, en el cual tenía que extraer las facturas pendientes de pago, pero por mes.

-- =============================================
-- Author:  Ing. DEBS
-- Create date: 13/02/2014
-- Description: Devuelve por mes (año actual)
--    las facturas pendientes de los proveedores
-- =============================================
ALTER PROCEDURE [Exo].[GetFCxPrvxYear]
 @cYear varchar(4)=''
AS
BEGIN
 /*Declare @cYear as varchar(4);
 Set @cYear = Convert(varchar(4),Year(GetDate()));
 */
 IF @cYear = ''
 BEGIN
  Set @cYear = Convert(varchar(4),Year(GetDate()))
 END

 ;With CTE1  --Llama la CTE y sus valores y convierte a C$ todo
  as
 (
 Select cDescPrv,cCodPrv,
  case when cCodMon='C$' THEN nMonto ELSE Round(nMonto * nTC,2) end as nMonto,
  case when cCodMon='C$' THEN nExonerado ELSE Round(nExonerado * nTC,2) end as nExonerado,
  case when cCodMon='C$' THEN nSaldo ELSE Round(nSaldo * nTC,2) end as nSaldo,
  left(YearMes,4) as cYear,Right(YearMes,2) as cMes
  from Exo.GetFCSaldos() 
  where nSaldo<>0
  and nMonto>=0 and nExonerado>=0 and nSaldo>=0
 ),-- CTE2 Ubica cada valor en el mes correspondiente
 CTE2 (cDescPrv,cCodPrv,Saldo_Ant,Ene,Feb,Mar,Abr,May,Jun,Jul,Ago,Sep,Oct,Nov,Dic) 
  as
 (
  Select cDescPrv,cCodPrv,
   case when cYear < @cYear then Sum(nSaldo) ELSE 0.0 END,
   Case when cMes = '01' and cYear = @cYear then Sum(nSaldo) else 0.00 end,
   Case when cMes = '02' and cYear = @cYear  then Sum(nSaldo) else 0.00 end,
   Case when cMes = '03' and cYear = @cYear  then Sum(nSaldo) else 0.00 end,
   Case when cMes = '04' and cYear = @cYear  then Sum(nSaldo) else 0.00 end,
   Case when cMes = '05' and cYear = @cYear  then Sum(nSaldo) else 0.00 end,
   Case when cMes = '06' and cYear = @cYear  then Sum(nSaldo) else 0.00 end,
   Case when cMes = '07' and cYear = @cYear  then Sum(nSaldo) else 0.00 end,
   Case when cMes = '08' and cYear = @cYear  then Sum(nSaldo) else 0.00 end,
   Case when cMes = '09' and cYear = @cYear  then Sum(nSaldo) else 0.00 end,
   Case when cMes = '10' and cYear = @cYear  then Sum(nSaldo) else 0.00 end,
   Case when cMes = '11' and cYear = @cYear  then Sum(nSaldo) else 0.00 end,
   Case when cMes = '12' and cYear = @cYear  then Sum(nSaldo) else 0.00 end
  from CTE1
  group by cDescPrv,cCodPrv,cYear,cMes
 ) --Se procede a sumar todo y listo
 Select cDescPrv,cCodPrv,Sum(Saldo_Ant) as Anterior,
  Sum(Ene) as Enero,
  Sum(Feb) as Febrero,
  Sum(Mar) as Marzo,
  Sum(Abr) as Abril,
  Sum(May) as Mayo,
  Sum(Jun) as Junio,
  Sum(Jul) as Julio,
  Sum(Ago) as Agosto,
  Sum(Sep) as Septiembre,
  Sum(Oct) as Octubre,
  Sum(Nov) as Noviembre,
  Sum(Dic) as Diciembre,
  Sum(Saldo_Ant + Ene + Feb + Mar + Abr + May + Jun + Jul + Ago + Sep + Oct + Nov + Dic) as Total
 from CTE2
 where
  (Saldo_Ant + Ene + Feb + Mar + Abr + May + Jun + Jul + Ago + Sep + Oct + Nov + Dic)<>0
  group by cDescPrv,cCodPrv
  order by cDescPrv,cCodPrv
END


Una ejecución a este SP, es algo así:

Conclusión

Las CTE's son muy útiles para poder aplicar recursividad a la información que queremos filtrar, esto es, aplicar ciertas operaciones (o filtro) sobre un conjunto de registros que previamente extrajimos (o consultamos) de la BD.

Como verán en el ejemplo que puse ya al final, utilicé dos CTE, la primera (CTE1) se encarga de poner todos los montos en moneda nacional (de no estarlo), a partir de los datos de una TVF (Exo.GetFCSaldos()) así como filtrar únicamente los registros que aún tienen saldo, además de poner los dos primeros dígitos del mes, luego en la segunda CTE (CTE2) se realiza la sumatoria por mes de cada registro del año correspondiente, asignándoles el nombre del mes.  Al final, se muestran los datos, a partir de la CTE2 y se totaliza por registros.  Puede que la solución es bastante compleja y existen métodos más sencillos, pero traté de ponerles una aplicación práctica de CTE.

Para más información sobre CTE's, pueden visitar los siguientes sitios:
Gracias por haber tomado el tiempo de leer este artículo, espero te sea de utilidad y de serlo, favor compartirlo.  Igual, si tenés alguna duda, comenta en esta publicación.

"Enseñar es la mejor forma de Aprender"


viernes, 23 de mayo de 2014

Table Value Function - SQL Server




Una TVF (Table Value Functions, Función con Valores de Tabla), son funciones definidas por el usuario muy parecidas a las vistas, pero con la particularidad que pueden recibir parámetros, así que podríamos decir que son como vistas, pero que reciben parámetros.

En algunos casos, las TVF podrían reemplazar los procedimientos almacenados (SP, Store Procedure), o bien poder ser utilizados dentro de los mismos.

Son muy útiles, ya que disminuye el tamaño de una consulta, que puede llegar a ser más compleja, permitiendo mejor legibilidad de la misma.

Sintaxis



Características:

  • TVF's retornan una tabla virtual, llamada consulta (query)
  • SQL Server provee dos tipos de TVF
    • Inline: basada de una única expresión SELECT
    • Multi-Statement: Crea y carga varias tablas
  • Soportan parámetros de entrada (no así las vistas).
  • Una TVF Inline, puede ser pensada como una vista parametrizada.

Ejemplo de TVF's



Veremos la utilización dentro de una consulta de la TVF llamada CxC.AntSald_Det, la cual recibe como parámetro el Id de empresa y filtra la información únicamente para esa condición.


Select a.cCodProc,b.cDescript,

Sum(a.Saldo) as Saldo

from CxC.AntSald_Det(@cEmpresa) a inner join CxCProc b on (a.cCodProc=b.cCodProc)

group by a.cCodProc,b.cDescrip

order by a.cCodProc

 Conclusión

La utilización de TVF ayudará mucho, tanto a tener un código más legible, como a realizar consultas complejas.  Por lo que recomiendo su uso. En otro artículo veremos la utilización de los CTE (Common Table Expressions).

Gracias por leer y espero que te sea de utilidad este pequeño artículo.


Bosquejo con Photohop

 
En este video, también sacando un poco de la colección de videos que tenemos por ahí, veremos cómo hacer un bosquejo de una fotografía, utilizando Photoshop, espero les sea de utilidad este video y ya saben, si les es de utilidad compartan el video.
 
 

jueves, 22 de mayo de 2014

Gif Animado con Photoshop


Vídeo algo viejito, pero aún válido, de cómo hacer un gif animado utilizando photoshop. 

Esquinas Dobladas con Photoshop



Pequeño tutorial donde indicamos cómo trabajar con Photoshop y esquinas dobladas

 
>