If it is MySql you can try SELECT @n := @n + 1 n, first_name, last_name FROM table1, (SELECT @n := 0) m ORDER BY first_name, last_name SQLFiddle And for SQLServer SELECT row_number() OVER (ORDER BY first_name, last_name) n, first_name, last_name FROM table1 here's for SQL server, Oracle, PostgreSQL which support window functions. SELECT ROW_NUMBER() OVER (ORDER BY first_name, last_name) Sequence_no, first_name, last_name FROM tableName SQLFiddle Demo
Si llamamos a la funcin anterior sin enviarle los valores para los parmetros: select dbo.f_promedio(); SQL Server muestra un mensaje de error indicando que necesita argumentos. Creamos una funcin a la cual le enviamos una fecha y nos retorna el nombre del mes en espaol: create function f_nombreMes (@fecha datetime='2007/01/01') returns varchar(10) as begin declare @nombre varchar(10) set @nombre= case datename(month,@fecha) when 'January' then 'Enero' when 'February' then 'Febrero' when 'March' then 'Marzo' when 'April' then 'Abril' when 'May' then 'Mayo' when 'June' then 'Junio' when 'July' then 'Julio' when 'August' then 'Agosto' when 'September' then 'Setiembre' when 'October' then 'Octubre' when 'November' then 'Noviembre' when 'December' then 'Diciembre' end--case return @nombre end; Analicemos: luego de "create function" y el nombre de la funcin, especificamos los parmetros de entrada con sus tipos de datos (entre parntesis). El parmetro de entrada tiene definido un valor por defecto. Luego de los parmetros de entrada se indica el tipo de dato que retorna luego de "returns"; luego de "as" comienza el bloque "begin...end" dentro del cual se encuentran las instrucciones de procesamiento y el valor retornado luego de "return". Las funciones que retornan un valor escalar pueden emplearse en cualquier consulta donde se coloca un campo. Recuerde que al invocar una funcin escalar, se debe especificar el propietario y el nombre de la funcin: select nombre, dbo.f_nombreMes(fechaingreso) as 'mes de ingreso' from empleados; No olvide que cuando invocamos funciones que tienen definidos parmetros de entrada DEBEMOS suministrar SIEMPRE un valor para l.
Podemos colocar un valor por defecto al parmetro, pero al invocar la funcin, para que tome el valor por defecto DEBEMOS especificar "default". Por ejemplo, si llamamos a la funcin anterior sin enviarle un valor: select dbo.f_nombreMes(); SQL Server muestra un mensaje de error indicando que necesita argumento. Para que tome el valor por defecto debemos enviar "default" como argumento: select dbo.f_nombreMes(default); La instruccin "create function" debe ser la primera sentencia de un lote.
Existen tres tipos de funciones en SQL Server una parece ser como el tipo de funciones de los leguajes de programacin donde se le enva un valor y retorna un resulta a esta se les llama funciones escalares, los otros dos tipos de funciones resultan un hibrido entre vista y procedimiento almacenado, permitiendo enviar parmetros a una consulta, en este video se revisa su funcionamiento.
Use northwind go 1.Creacion de Funciones Escalares CREATE FUNCTION Iva (@DATE money) RETURNS money AS BEGIN Declare @iva money Set @Iva=@date*.12 Return(@iva) END 3.Revisar la funcion debe de escribirse el nombre con dos partes Select unitprice, dbo.iva(unitprice) as ivafrom [ord er details] 4.borrar la funcion drop function iva 5.Otro ejemplo de funcion CREATE Function Comision(@valor money) ReturnS money
96 - Exists y No Exists
Los operadores "exists" y "not exists" se emplean para determinar si hay o no datos en una lista de valores. Estos operadores pueden emplearse con subconsultas correlacionadas para restringir el resultado de una consulta exterior a los registros que cumplen la subconsulta (consulta interior). Estos operadores retornan "true" (si las subconsultas retornan registros) o "false" (si las subconsultas no retornan registros). Cuando se coloca en una subconsulta el operador "exists", SQL Server analiza si hay datos que coinciden con la subconsulta, no se devuelve ningn registro, es como un test de existencia; SQL Server termina la recuperacin de registros cuando por lo menos un registro cumple la condicin "where" de la subconsulta. La sintaxis bsica es la siguiente: ... where exists (SUBCONSULTA); En este ejemplo se usa una subconsulta correlacionada con un operador "exists" en la clusula "where" para devolver una lista de clientes que compraron el artculo "lapiz": select cliente,numero from facturas as f where exists (select *from Detalles as d where f.numero=d.numerofactura and d.articulo='lapiz'); Puede obtener el mismo resultado empleando una combinacin. Podemos buscar los clientes que no han adquirido el artculo "lapiz" empleando "if not exists": select cliente,numero from facturas as f where not exists (select *from Detalles as d where f.numero=d.numerofactura and d.articulo='lapiz');
Este tema an no ha recibido ninguna valoracin - Valorar este tema Una clave principal de una base de datos relacional es una columna o combinacin de columnas que siempre contienen valores nicos. Conocer el valor de la clave principal permite localizar la fila que la contiene. Los motores de bases de datos relacionales, como SQL Server, Oracle y Microsoft Access/Jet admiten la creacin de columnas de incremento automtico que pueden designarse como claves principales. Estos valores los genera el servidor cuando se agregan filas a una tabla. En SQL Server se establece la propiedad de identidad de una columna, en Oracle se crea una secuencia y en Microsoft Access se crea una columna Autonumrica. DataColumn tambin se puede utilizar para generar de manera automtica valores incrementales estableciendo la propiedad AutoIncrement en true. No obstante, podra haber valores duplicados en instancias distintas de DataTable si varias aplicaciones cliente estn generando por separado valores incrementales de manera automtica. Si se tiene un servidor que genera de manera automtica valores incrementales se eliminan posibles conflictos, pues se permite a cada usuario recuperar el valor generado para cada fila insertada. Durante una llamada al mtodo Update de DataAdapter, la base de datos puede volver a enviar datos a la aplicacin ADO.NET como parmetros de salida o como el primer registro devuelto del conjunto de resultados de una instruccin SELECT ejecutada en el mismo lote que la instruccin INSERT. ADO.NET puede recuperar estos valores y actualizar las columnas correspondientes en el DataRow que se est actualizando. Algunos motores de base de datos, como los de Microsoft Access Jet, no admiten parmetros de salida y no pueden procesar varias instrucciones en un nico lote. Cuando trabaje con el motor de base de datos de Jet, puede recuperar el nuevo valor Autonumrico generado para una fila insertada ejecutando un comando SELECT distinto en un controlador de eventos para el evento RowUpdated de DataAdapter.
Nota
Una opcin alternativa al uso de un valor de incremento automtico es utilizar el mtodo NewGuid de un obj (identificador nico global) en el equipo cliente que se pueda copiar al servidor cuando se inserte una nueva f
binario de 16 bits que se crea mediante un algoritmo que permite que haya una alta probabilidad de que no se de SQL Server, el GUID se almacena en una columnauniqueidentifier que SQL Server puede generar autom SQL NEWID(). Utilizar un GUID como clave principal puede afectar de manera negativa al rendimiento. SQ funcin NEWSEQUENTIALID(), que genera un GUID secuencial que no est garantizado que sea nico gl forma ms eficaz.
Funcin SCOPE_IDENTITY
Descripcin Devuelve el ltimo valor de identidad en el mbito de ejecucin actual. SCOPE_IDENTITY se recomienda en la mayora de los casos. Contiene el ltimo valor de identidad generado en cualquier tabla de la sesin actual. @@IDENTITY puede verse afectado por los desencadenadores y no devolver el valor de identidad esperado. Devuelve el ltimo valor de identidad generado para una tabla concreta de cualquier sesin y en cualquier mbito.
@@IDENTITY
IDENT_CURRENT
El siguiente procedimiento almacenado muestra cmo insertar una fila en la tabla Categories y utilizar un parmetro de salida para devolver el nuevo valor de identidad generado por la funcin Transact-SQL SCOPE_IDENTITY(). CREATE PROCEDURE dbo.InsertCategory @CategoryName nvarchar(15), @Identity int OUT AS INSERT INTO Categories (CategoryName) VALUES(@CategoryName) SET @Identity = SCOPE_IDENTITY() El procedimiento almacenado se puede especificar como el origen de InsertCommand de un objeto SqlDataAdapter.La propiedad CommandType de InsertCommand debe establecerse en StoredProcedure.La salida de identidad se recupera creando un SqlParameter que tiene un ParameterDirection de Output.Cuando se procesaInsertCommand, el valor de identidad de incremento automtico se devuelve y se coloca en la columna CategoryID de la fila actual si se establece la propiedadUpdatedRowSource del comando de insercin en UpdateRowSource.OutputParameters o UpdateRowSource.Both. Si el comando de insercin ejecuta un lote que incluye tanto una instruccin INSERT como una instruccin SELECT que devuelven el nuevo valor de identidad, entonces puede recuperar el nuevo
valor estableciendo la propiedad UpdatedRowSource del comando de insercin en UpdateRowSource.FirstReturnedRecord. C# VB private static void RetrieveIdentity(string connectionString) { using (SqlConnection connection = new SqlConnection(connectionString)) { // Create a SqlDataAdapter based on a SELECT query. SqlDataAdapter adapter = new SqlDataAdapter( "SELECT CategoryID, CategoryName FROM dbo.Categories", connection); //Create the SqlCommand to execute the stored procedure. adapter.InsertCommand = new SqlCommand("dbo.InsertCategory", connection); adapter.InsertCommand.CommandType = CommandType.StoredProcedure; // Add the parameter for the CategoryName. Specifying the // ParameterDirection for an input parameter is not required. adapter.InsertCommand.Parameters.Add( new SqlParameter("@CategoryName", SqlDbType.NVarChar, 15, "CategoryName")); // Add the SqlParameter to retrieve the new identity value. // Specify the ParameterDirection as Output. SqlParameter parameter = adapter.InsertCommand.Parameters.Add( "@Identity", SqlDbType.Int, 0, "CategoryID"); parameter.Direction = ParameterDirection.Output; // Create a DataTable and fill it. DataTable categories = new DataTable(); adapter.Fill(categories); // Add a new row. DataRow newRow = categories.NewRow(); newRow["CategoryName"] = "New Category"; categories.Rows.Add(newRow); adapter.Update(categories); Console.WriteLine("List All Rows:"); foreach (DataRow row in categories.Rows) {
La siguiente tabla describe cmo afectan los valores de enumeracin UpdateRowSource a la propiedad RowState de las filas actualizadas.
Descripcin
Se llama a AcceptChanges y tanto los parmetros de salida como los valores de resultados devuelto se colocan en la DataRow que se est actualizando. Si no hay aplicar, RowState ser Unchanged.
FirstReturnedRecord
Si se devuelve una fila, se llama a AcceptChanges y la fila se asigna a la fila mo estableciendo RowState en Modified. Si no se devuelve ninguna fila, entonces n a AcceptChanges y RowState permanece en Added.
None
Se pasan por alto todos los parmetros o filas devueltos. No hay llamada a Accep en Added.
OutputParameters
Se llama a AcceptChanges y todos los parmetros de salida se asignan a la fila m estableciendo RowState en Modified.Si no hay parmetros de salida, RowState
Ejemplo
Este ejemplo muestra la extraccin de filas modificadas desde DataTable y el uso de SqlDataAdapter para actualizar el origen de datos y recuperar un nuevo valor de columna de identidad. InsertCommand ejecuta dos instrucciones Transact-SQL; la primera es la instruccin INSERT y la segunda es la instruccin SELECT. INSERT INTO dbo.Shippers (CompanyName) VALUES (@CompanyName); SELECT ShipperID, CompanyName FROM dbo.Shippers WHERE ShipperID = SCOPE_IDENTITY(); La propiedad UpdatedRowSource del comando de insercin se establece en UpdateRowSource.FirstReturnedRow y la propiedad MissingSchemaAction de DataAdapterse establece en MissingSchemaAction.AddWithKey. DataTable se rellena y el cdigo agrega una nueva fila a DataTable.A continuacin, las filas modificadas se extraen en un nuevo DataTable, que se pasa a DataAdapter, el cual actualiza el servidor. C# VB private static void MergeIdentityColumns(string connectionString) { using (SqlConnection connection = new SqlConnection(connectionString)) { // Create the DataAdapter SqlDataAdapter adapter = new SqlDataAdapter( "SELECT ShipperID, CompanyName FROM dbo.Shippers", connection);
//Add the InsertCommand to retrieve new identity value. adapter.InsertCommand = new SqlCommand( "INSERT INTO dbo.Shippers (CompanyName) " + "VALUES (@CompanyName); " + "SELECT ShipperID, CompanyName FROM dbo.Shippers " + "WHERE ShipperID = SCOPE_IDENTITY();", connection); // Add the parameter for the inserted value. adapter.InsertCommand.Parameters.Add( new SqlParameter("@CompanyName", SqlDbType.NVarChar, 40, "CompanyName")); adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.Both; // MissingSchemaAction adds any missing schema to // the DataTable, including identity columns adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey; // Fill the DataTable. DataTable shipper = new DataTable(); adapter.Fill(shipper); // Add a new shipper. DataRow newRow = shipper.NewRow(); newRow["CompanyName"] = "New Shipper"; shipper.Rows.Add(newRow); // Add changed rows to a new DataTable. This // DataTable will be used by the DataAdapter. DataTable dataChanges = shipper.GetChanges(); // Add the event handler. adapter.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated); adapter.Update(dataChanges); connection.Close(); // Merge the updates. shipper.Merge(dataChanges); // Commit the changes. shipper.AcceptChanges(); Console.WriteLine("Rows after merge."); foreach (DataRow row in shipper.Rows) { { Console.WriteLine("{0}: {1}", row[0], row[1]);
} } } }
El controlador de eventos OnRowUpdated comprueba StatementType de SqlRowUpdatedEventArgs para determinar si la fila es una insercin.Si lo es, entonces la propiedad se establece Status en SkipCurrentRow.La fila est actualizada, pero los valores originales de la fila se mantienen.En el cuerpo principal del procedimiento, se llama al mtodo Merge para combinar el nuevo valor de identidad en el DataTable original y, finalmente, se llama a AcceptChanges. C# VB protected static void OnRowUpdated( object sender, SqlRowUpdatedEventArgs e) { // If this is an insert, then skip this row. if (e.StatementType == StatementType.Insert) { e.Status = UpdateStatus.SkipCurrentRow; } }
Ejemplo
En lugar de agregar informacin de esquema utilizando MissingSchemaAction.AddWithKey, este ejemplo configura DataTable con el esquema adecuado antes de llamar a OleDbDataAdapter para rellenar DataTable. En este caso, la columna CategoryID se configura para disminuir el valor asignado a cada fila insertada empezando desde cero, estableciendo AutoIncrement en true, AutoIncrementSeed en 0 y AutoIncrementStep en 1. Entonces, el cdigo agrega dos filas nuevas y utiliza GetChanges para agregar las filas modificadas a un nuevo DataTable que se pasa al mtodo Update. C# VB
private static OleDbConnection connection = null; private static void MergeIdentityColumns(OleDbConnection connection) { using (connection) { // Create a DataAdapter based on a SELECT query. OleDbDataAdapter adapter = new OleDbDataAdapter( "SELECT CategoryID, CategoryName FROM Categories", connection); // Create the INSERT command for the new category. adapter.InsertCommand = new OleDbCommand( "INSERT INTO Categories (CategoryName) Values(?)", connection); adapter.InsertCommand.CommandType = CommandType.Text; // Add the parameter for the CategoryName. adapter.InsertCommand.Parameters.Add( "@CategoryName", OleDbType.VarWChar, 15, "CategoryName"); adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.Both; // Create a DataTable DataTable categories = new DataTable(); // Create the CategoryID column and set its auto // incrementing properties to decrement from zero. DataColumn column = new DataColumn(); column.DataType = System.Type.GetType("System.Int32"); column.ColumnName = "CategoryID"; column.AutoIncrement = true; column.AutoIncrementSeed = 0; column.AutoIncrementStep = -1; categories.Columns.Add(column); // Create the CategoryName column. column = new DataColumn(); column.DataType = System.Type.GetType("System.String"); column.ColumnName = "CategoryName"; categories.Columns.Add(column); // Set the primary key on CategoryID. DataColumn[] pKey = new DataColumn[1]; pKey[0] = categories.Columns["CategoryID"]; categories.PrimaryKey = pKey; // Fetch the data and fill the DataTable adapter.Fill(categories);
// Add a new row. DataRow newRow = categories.NewRow(); newRow["CategoryName"] = "New Category"; categories.Rows.Add(newRow); // Add another new row. DataRow newRow2 = categories.NewRow(); newRow2["CategoryName"] = "Another New Category"; categories.Rows.Add(newRow2); // Add changed rows to a new DataTable that will be // used to post the inserts to the database. DataTable dataChanges = categories.GetChanges(); // Include an event to fill in the Autonumber value. adapter.RowUpdated += new OleDbRowUpdatedEventHandler(OnRowUpdated); // Update the database, inserting the new rows. adapter.Update(dataChanges); Console.WriteLine("Rows before merge:"); foreach (DataRow row in categories.Rows) { { Console.WriteLine(" {0}: {1}", row[0], row[1]); } } // Merge the two DataTables. categories.Merge(dataChanges); // Commit the changes. categories.AcceptChanges(); Console.WriteLine("Rows after merge:"); foreach (DataRow row in categories.Rows) { { Console.WriteLine(" {0}: {1}", row[0], row[1]); } } } }
El controlador de eventos RowUpdated utiliza el mismo OleDbConnection abierto que la instruccin Update de OleDbDataAdapter. Comprueba el StatementType deOleDbRowUpdatedEventArgs de las filas insertadas. Se crea un
nuevo OleDbCommand en cada nueva fila insertada para ejecutar la instruccin SELECT @@IDENTITY en la conexin, devolviendo el nuevo valor Autonumber, que est situado en la columna CategoryID de DataRow. La propiedad Status se establece luego enUpdateStatus.SkipCurrentRow para suprimir la llamada oculta a AcceptChanges. En el cuerpo principal del procedimiento, se llama al mtodo Merge para combinar los dos objetos DataTable y, finalmente, se llama a AcceptChanges. C# VB private static void OnRowUpdated( object sender, OleDbRowUpdatedEventArgs e) { // Conditionally execute this code block on inserts only. if (e.StatementType == StatementType.Insert) { OleDbCommand cmdNewID = new OleDbCommand("SELECT @@IDENTITY", connection); // Retrieve the Autonumber and store it in the CategoryID column. e.Row["CategoryID"] = (int)cmdNewID.ExecuteScalar(); e.Status = UpdateStatus.SkipCurrentRow; } }
Vea tambin
Conceptos
Estados de fila y versiones de fila AcceptChanges y RejectChanges Combinar contenido de DataSet Actualizar orgenes de datos con DataAdapters
Otros recursos
Recuperacin y modificacin de datos en ADO.NET DataAdapters y DataReaders Proveedores administrados de ADO.NET y centro de desarrolladores de DataSet
DENT_CURRENT (Transact-SQL)
SQL Server 2012 Otras versiones
Personas que lo han encontrado til: 2 de 2 - Valorar este tema Devuelve el ltimo valor de identidad generado para una tabla o vista especificadas. El ltimo valor de identidad generado puede ser para cualquier sesin y cualquier mbito. Convenciones de sintaxis de Transact-SQL
Sintaxis
IDENT_CURRENT( 'table_name' )
Argumentos
table_name Es el nombre de la tabla cuyo valor de identidad se devuelve. table_name es de tipo varchar y no tiene valor predeterminado.
Excepciones
Devuelve NULL si se produce un error o si el autor de la llamada no tiene permiso para ver el objeto. En SQL Server, un usuario solo puede ver los metadatos de elementos protegibles que posea o para los que se le haya concedido permiso. Esto significa que las funciones integradas de emisin de metadatos, como IDENT_CURRENT, pueden devolver NULL si el usuario no tiene ningn permiso para el objeto. Para obtener ms informacin, vea Configuracin de visibilidad de los metadatos.
Comentarios
IDENT_CURRENT es similar a las funciones de identidad SCOPE_IDENTITY e @@IDENTITY de SQL Server 2000. Las tres funciones devuelven los ltimos valores de identidad generados. Pero la definicin de los ltimos valores de identidad difiere en el mbito y la sesin para cada una de estas funciones. IDENT_CURRENT devuelve el ltimo valor de identidad generado para una tabla especfica en cualquier sesin y cualquier mbito. @@IDENTITY devuelve el ltimo valor de identidad generado para cualquier tabla en la sesin actual, en todos los mbitos.
SCOPE_IDENTITY devuelve el ltimo valor de identidad generado para cualquier tabla en la sesin y el mbito actuales. Cuando el valor de IDENT_CURRENT es NULL (porque la tabla nunca ha contenido filas ni ha sido truncada), la funcin IDENT_CURRENT devuelve el valor de inicializacin. Las instrucciones y transacciones con errores pueden cambiar la identidad actual de una tabla y crear espacios en los valores de la columna de identidad. El valor de identidad jams se revierte, aun cuando no se haya confirmado la transaccin que intent insertar el valor en la tabla. Por ejemplo, si se produce un error en una instruccin INSERT debido a una infraccin de IGNORE_DUP_KEY, el valor de identidad actual de la tabla se sigue incrementando. Tenga cuidado al usar IDENT_CURRENT para predecir el siguiente valor de identidad generado. El valor generado real puede ser diferente de IDENT_CURRENT ms IDENT_INCR a causa de las inserciones realizadas por otras sesiones.
Ejemplos
A.Devolver el ltimo valor de identidad generado para una tabla especificada
En el ejemplo siguiente se devuelve el ltimo valor de identidad generado para la tabla Person.Address en la base de datos AdventureWorks2012. USE AdventureWorks2012; GO SELECT IDENT_CURRENT ('Person.Address') AS Current_Identity; GO
SELECT id FROM t7; --ID is empty. --Do the following in Session 1 INSERT t6 DEFAULT VALUES; SELECT @@IDENTITY; /*Returns the value 100. This was inserted by the trigger.*/ SELECT SCOPE_IDENTITY(); /* Returns the value 1. This was inserted by the INSERT statement two statements before this query.*/ SELECT IDENT_CURRENT('t7'); /* Returns value inserted into t7, that is in the trigger.*/ SELECT IDENT_CURRENT('t6'); /* Returns value inserted into t6. This was the INSERT statement four statements before this query.*/ -- Do the following in Session 2. SELECT @@IDENTITY; /* Returns NULL because there has been no INSERT action up to this point in this session.*/ SELECT SCOPE_IDENTITY(); /* Returns NULL because there has been no INSERT action up to this point in this scope in this session.*/ SELECT IDENT_CURRENT('t7'); /* Returns the last value inserted into t7.*/
Vea tambin
Referencia
@@IDENTITY (Transact-SQL) SCOPE_IDENTITY (Transact-SQL) IDENT_INCR (Transact-SQL) IDENT_SEED (Transact-SQL) Expresiones (Transact-SQL) Funciones del sistema (Transact-SQL)
En diversas ocasiones muchos de nuestros alumnos nos han preguntado, como obtener el id del ultimo registro insertado y si tu eres programador sabrs lo til que resulta obtener el ultimo valor del id para despus utilizarlo en alguna otra operacin y/o consulta. En esta ocasin nos enfocaremos a bases de datos MySQL y SQL Server. Para que las siguientes operaciones funcionen adecuadamente es necesario que el campo id sea indice (MySQL) o clave principal (SQL Server) y que sea auto-increment (autonumerico). Empezemos
@@identity Este es un metodo muy conocido, consiste en utilizar la sintaxis SELECT @@identity AS id y devuelve el id del ultimo ingreso, por ello se debe utilizar inmediatamente despus de usar la sentencia INSERT.
Ejemplo con PHP y MySQL
MAX(id) Otra forma es mediante la sentencia SELECT MAX(id) AS id FROM tabla. La ventaja de este mtodo con respecto al anterior es que no es necesario utilizarlo inmediatamente despues de utilizar la sentencia INSERT; ya que este mtodo busca el id de mayor valor dentro de la tabla y como es auto incrementable el mayor siempre sera el ultimo.
Ejemplo con PHP y MySQL
dt.Load(command.ExecuteReader) id = dt.Rows(0).Item(0).ToString()
mysql_insert_id Este metodo funciona solo con PHP y MySQL: mysql_insert_id(). Al igual que la propiedad @@identity, solo retorna el id del ultimo registro ingresado independientemente de la tabla en la que se haya realizado la operacion.
$id=mysql_insert_id();
OBTENER EL ULTIMO IDOBTENER ULTIMO ID INSERTADOULTIMO IDULTIMO ID DE BASE MYSQLULTIMO ID DE BASE SQL SERVER
SCOPE_IDENTITY (Transact-SQL)
SQL Server 2012 Otras versiones
Personas que lo han encontrado til: 6 de 7 - Valorar este tema Devuelve el ltimo valor de identidad insertado en una columna de identidad en el mismo mbito. Un mbito es un mdulo: un procedimiento almacenado, desencadenador, funcin o lote. Por tanto, dos instrucciones estn en el mismo mbito si se encuentran en el mismo procedimiento almacenado, funcin o lote. Convenciones de sintaxis de Transact-SQL
Sintaxis
SCOPE_IDENTITY()
Comentarios
SCOPE_IDENTITY, IDENT_CURRENT y @@IDENTITY son funciones parecidas ya que devuelven valores insertados en columnas de identidad. IDENT_CURRENT no est limitado por el mbito y la sesin; se limita a una tabla especificada. IDENT_CURRENT devuelve el valor generado para una tabla especfica en cualquier sesin y cualquier mbito. Para obtener ms informacin, vea IDENT_CURRENT (Transact-SQL). SCOPE_IDENTITY y @@IDENTITY devuelven los ltimos valores de identidad generados en una tabla en la sesin actual. No obstante, SCOPE_IDENTITY solo devuelve los valores insertados en el mbito actual; @@IDENTITY no se limita a un mbito especfico. Por ejemplo, suponga que hay dos tablas, T1 y T2, y un desencadenador INSERT definido en T1. Cuando se inserta una fila en T1, el desencadenador se activa e inserta una fila en T2. Este escenario muestra dos mbitos: la insercin en T1 y la insercin en T2 como resultado del desencadenador. Suponiendo que T1 y T2 tienen columnas de identidad, @@IDENTITY y SCOPE_IDENTITY devolvern distintos valores al finalizar una instruccin INSERT en T1. @@IDENTITY devolver el ltimo valor de la columna de identidad insertado en cualquier mbito en la sesin actual. En este caso, se trata del valor insertado en T2. SCOPE_IDENTITY() devolver el valor IDENTITY insertado en T1. Es la ltima insercin que se ha producido en el mismo mbito. La funcin SCOPE_IDENTITY() devolver el valor NULL si se llama a la funcin antes de que se ejecuten las instrucciones INSERT en una columna de identidad en el mbito. Las instrucciones y transacciones con errores pueden cambiar la identidad actual de una tabla y crear huecos en los valores de columna de identidad. El valor de identidad jams se revierte, aun cuando no se haya confirmado la transaccin que intent insertar el valor en la tabla. Por ejemplo, si
se produce un error en una instruccin INSERT debido a una infraccin de tipo IGNORE_DUP_KEY, el valor de identidad actual de la tabla se sigue incrementando.
Ejemplos
A.Usar @@IDENTITY y SCOPE_IDENTITY con desencadenadores
Este ejemplo crea dos tablas, TZ y TY, y un desencadenador INSERT en TZ. Cuando se inserta una fila en TZ, el desencadenador Ztrig se activa e inserta una fila en TY. USE tempdb GO CREATE TABLE TZ ( Z_id int IDENTITY(1,1)PRIMARY KEY, Z_name varchar(20) NOT NULL) INSERT TZ VALUES ('Lisa') INSERT TZ VALUES ('Mike') INSERT TZ VALUES ('Carla') SELECT * FROM TZ --Result set: This is how table TZ looks. Z_id Z_name ------------1 Lisa 2 Mike 3 Carla CREATE TABLE TY ( Y_id int IDENTITY(100,5)PRIMARY KEY, Y_name varchar(20) NULL) INSERT TY VALUES INSERT TY VALUES INSERT TY VALUES (Y_name) ('boathouse') (Y_name) ('rocks') (Y_name) ('elevator')
SELECT * FROM TY --Result set: This is how TY looks: Y_id Y_name --------------100 boathouse 105 rocks 110 elevator /*Create the trigger that inserts a row in table TY when a row is inserted in table TZ.*/
CREATE TRIGGER Ztrig ON TZ FOR INSERT AS BEGIN INSERT TY VALUES ('') END /*FIRE the trigger and determine what identity values you obtain with the @@IDENTITY and SCOPE_IDENTITY functions.*/ INSERT TZ VALUES ('Rosalie') SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY] GO SELECT @@IDENTITY AS [@@IDENTITY] GO El conjunto de resultados es el siguiente. SCOPE_IDENTITY 4 /*SCOPE_IDENTITY returned the last identity value in the same scope. This was the insert on table TZ.*/ @@IDENTITY 115 /*@@IDENTITY returned the last identity value inserted to TY by the trigger. This fired because of an earlier insert on TZ.*/
Los ejemplos siguientes muestran cmo se usan @@IDENTITY y SCOPE_IDENTITY() para las inserciones en una base de datos publicada para la replicacin de mezcla. Las dos tablas de los ejemplos se encuentran en la base de datos de ejemplo AdventureWorks2012 : Person.ContactType no est publicado y Sales.Customer s. La replicacin de mezcla agrega desencadenadores a las tablas publicadas. Por lo tanto, @@IDENTITY puede devolver el valor de la insercin en una tabla de sistema de replicacin en lugar de la insercin en una tabla de usuario. La tabla Person.ContactType tiene un valor de identidad mximo de 20. Si inserta una fila en la tabla, @@IDENTITY y SCOPE_IDENTITY() devolvern el mismo valor. USE AdventureWorks2012; GO INSERT INTO Person.ContactType ([Name]) VALUES ('Assistant to the Manager'); GO SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY]; GO SELECT @@IDENTITY AS [@@IDENTITY]; GO El conjunto de resultados es el siguiente. SCOPE_IDENTITY 21 @@IDENTITY 21
La tabla Sales.Customer tiene un valor de identidad mximo de 29483. Si inserta una fila en la tabla, @@IDENTITY y SCOPE_IDENTITY() devolvern valores diferentes.SCOPE_IDENTITY() devuelve el valor de la insercin en la tabla de usuario, mientras que @@IDENTITY devuelve el valor de la insercin en la tabla del sistema de replicacin.Use SCOPE_IDENTITY() para las aplicaciones que necesitan obtener acceso al valor de identidad insertado. INSERT INTO Sales.Customer ([TerritoryID],[PersonID]) VALUES (8,NULL); GO SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY]; GO SELECT @@IDENTITY AS [@@IDENTITY]; GO El conjunto de resultados es el siguiente. SCOPE_IDENTITY 29484 @@IDENTITY 89
Vea tambin
Referencia
@@IDENTITY (Transact-SQL)
Grimpi IT Blog
abril 3, 2008
Soluciones Para Actualizar Un Registro Si Existe, Sino Insertar En SQL Server.
Archivado en: SQL Server, T-SQL grimpi @ 2:06 am
3 Votes
Muchas veces cuando trabajamos con ABMs o algn proceso de escritura en la base de datos, al actualizar los registros, debemos establecer si vamos a efectuar un INSERT o un UPDATE. O sea, tenemos que determinar si el registro existe o no, para saber que operacin se va a efectuar en la base de datos. Generalmente se suele encapsular toda esta lgica dentro de un SP, algo que considero una muy buena practica, ya que nos desentendemos del lado de la aplicacin, si se va a efectuar una operacin de insercin o de modificacin. Primera solucin: Ahora bien, dentro del Store Procedure, lo solemos hacer para determinar la operacin, es el famoso IF EXISTS. Ejemplo: IF EXISTS(SELECT ID FROM TABLA WHERE ID = @ID) INSERT INTO TABLA (Campo1,ID) VALUES (@Valor,@ID) ELSE UPDATE TABLA SET Campo1 = @Valor WHERE ID = @ID No es un mal enfoque, es muy claro. Sin embargo esta solucin tiene dos inconvenientes: 1) Estamos pagando el costo de ejecutar un Query. Por mas que la consulta este indexada, tiene un costo. 2) No es 100% segura. En entornos muy demandantes, con alta concurrencia, puede darse el caso de que justo luego de ejecutar el IF EXISTS, otro proceso inserte en la tabla un registro con la misma PK y no tendramos forma de darnos cuenta, generando un error de duplicate key. Por lo tanto, esta opcin que es la ms comn, tiene serios inconvenientes.
Segunda solucin: Una segunda opcin podra ser esta: UPDATE TABLA SET Campo1 = @Valor WHERE ID = @ID IF @@ROWCOUNT = 0 INSERT INTO TABLA (Campo1,ID) VALUES (@Valor,@ID) En caso, se eliminara el tener que ejecutar una query con el EXISTS. Aunque en caso de que no exista el registro, se ejecuta el UPDATE innecesariamente. Si la mayora de las operaciones van a ser del tipo INSERT, en realidad no se ganara performance, pero por el contrario, si la mayora de las operaciones seria del tipo UPDATE, podra llegar a ser mas performante. De todas maneras esta solucin sigue teniendo el problema de que otro proceso podra insertar un registro con la misma PK en la tabla y no tendramos forma de darnos cuenta. Tercera solucin: En el segundo caso ganamos un poco de performance (no siempre), pero seguimos con el mismo problema de concurrencia. Pero ahora veamos este ejemplo de cdigo: BEGIN TRY INSERT INTO TABLA (Campo1,ID) VALUES (@Valor,@ID) END TRY BEGIN CATCH UPDATE TABLA SET Campo1 = @Valor WHERE ID = @ID END CATCH A nivel perfomance, es similar a las otras soluciones, pero si tenemos muchas ms operaciones de insercin que de actualizacin, vamos a ganar velocidad. Sin embargo, en este caso no tendramos el inconveniente de concurrencia que sucede en los 2 casos anteriores!!. Lo cual lo hace ideal para situaciones de alta demanda. Cuarta solucin (Solo en SQL Server 2008): SQL Server 2008, incorpora el comando MERGE (que ya tenamos en Oracle y otros motores), que sirve para resolver de una manera muy eficiente, exactamente este problema. MERGE TABLA USING (SELECT @ID AS ID) AS SRC ON SRC.ID = TABLA.ID WHEN MATCHED THEN UPDATE SET Campo1 = @Valor
WHEN NOT MATCHED THEN INSERT (Campo1,ID) VALUES (@Valor,@ID) Con este mtodo, tambin solucionamos el problema de concurrencia, y adems evitar tener que ejecutar consultas innecesarias. Por lo cual, podramos decir que es la optima solucin resolver este problema, aunque lamentablemente debemos esperar hasta mitad de ao, cuando Microsoft libere SQL Server 2008. Conclusin: Vimos como un problema en apariencia tonto y trivial, puede causar serios problemas de performance y peor aun, crear errores de concurrencia y comportamientos no deseados. Por las pruebas que hicimos en un entorno de TEST, la diferencia de performance que hicimos no son demasiadas. Pero en situaciones de alta concurrencia, las 2 primeras soluciones son definitivamente incorrectas. Recomiendo ver estos links, que explican como funcionan los lockeos, en cada una de las distintas soluciones: http://weblogs.sqlteam.com/mladenp/archive/2007/07/30/60273.aspx http://weblogs.sqlteam.com/mladenp/archive/2007/08/03/60277.aspx Y estas soluciones alternativas al mismo problema, tal vez sean un poco ms complejas, pero en algunos escenarios pueden ser tiles: http://www.samsaffron.com/blog/archive/2007/04/04/14.aspx http://www.sqlteam.com/article/application-locks-or-mutexes-in-sql-server-2005
If Dt.Rows.Count > 0 Then MessageBox.Show("Ya Existe", "Informacin", MessageBoxButtons.OK, MessageBoxIcon.Information) Else MessageBox.Show("no Existe Existe", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End If --------------------------------------... pero esta parte adaptalo a tu medida Dim Consulta As String = "SELECT CodCliente, NombCliente, Imagen FROM Clientes WHERE NombCliente='" & TextBox1.Text & "'" donde Con es la conexion buena suerte saludos
respondido hace 3 aos Primero tienes tener tu consulta SQL con este formato: Select count (*) as total_registros from [nombre_tabla] Luego en tu visual pones algo asi: total_registros= rs.recordcount donde rs es el Resulset generado al llamar a tu consulta SQL
papurri
validar si un registro existe antes de ejecutar insert
Fecha de Ingreso: agosto-2008 Ubicacin: Frente al pc Mensajes: 71 Antigedad: 5 aos, 7 meses Puntos: 2
Buenas. Tengo un procedimiento almacenado que inserta en una tabla. pero lo que necesito es que antes de relizar dicha operacion, se valide si el registro existe y justamente eso es lo que no se hacer, ya que mis conocimientos en t-sql son nulos. la clave primeria de mi tabla es un campo llamado rut, por lo que creo que debo consultar si existe un registros con una fila de datos que incluya ese rut. de todas formas dejo el condigo sql para ver si alguien me orienta en este tema saludos
ALTER procedure [dbo].[spInsertEjecutivo] ( @Nombres as varchar(50), @apellido_pat as varchar(50), @apellido_mat as varchar(50), @rut as varchar(50), @dv as int, @supervisor as varchar(100), @rut_supervisor as varchar(100), @plataforma as varchar(150), @user_ejecutivo as int )as if(@rut exist) Insert into ejecutivo ( nombres, apellido_pat, apellido_mat, rut, dv, supervisor, rut_supervisor,
plataforma, user_ejecutivo ) Values ( ltrim(rtrim(@Nombres)), ltrim(rtrim(@apellido_pat)), ltrim(rtrim(@apellido_mat)), ltrim(rtrim(@rut)), ltrim(rtrim(@dv)), ltrim(rtrim(@supervisor)), ltrim(rtrim(@rut_supervisor)), ltrim(rtrim(@plataforma)), ltrim(rtrim(@user_ejecutivo)) )
Avisos Google
devilguzz
Respuesta: validar si un registro existe antes de ejecutar insert
eso lo puedes hacer en la parte logica de tu aplicacion, pero si no deseas que sea asi.. puedes agregar que RUT sea UNIQUE
Avisos Google
AqpHost
ofertas en Hosting y dominios para tus clientes y proyectos web aqphost.com
__________________ GuzZpaWn
#3 (permalink) 05/07/2010, 07:35
-rommel_
Respuesta: validar si un registro existe antes de ejecutar insert
Fecha de Ingreso: junio-2008 Ubicacin: Lima Mensajes: 361 Antigedad: 5 aos, 9 meses Puntos: 1
y si antes de ejecutar ese Procedimiento "[dbo].[spInsertEjecutivo]" haces una validacion Cdigo PSEUDOCODIGO:
Ver original
1. PROCEDURE [dbo].[Condiciones] 2. 3. SI Cumple todas las condiciones ENTONCES 4. 5. EJCECUTAR [dbo].[spInsertEjecutivo] 6. 7. SINO 8. 9. MENSAJE "Existen Condiciones que no se Cumplen" 10. 11. FIN SI
iislas
Colaborador Respuesta: validar si un registro existe antes de ejecutar insert
Fecha de Ingreso: julio-2007 Ubicacin: Mexico, D.F. Mensajes: 5.921 Antigedad: 6 aos, 8 meses Puntos: 153
3 comentarios:
Annimo dijo...
Excelente inf
Gracias 7:22 p. m.
Saludos 8:35 a. m.
Annimo dijo...
todo bien pero en sql no me funciona a no ser que borre el "THEN", sin eso funciona perfecto. 11:17 a. m.
45
This is a pretty common situation that comes up when performing database operations. A stored procedure is called and the data needs to be updated if it already exists and inserted if it does not. If we refer to the Books Online documentation, it gives examples that are similar to: IF EXISTS (SELECT * FROM Table1 WHERE Column1='SomeValue') UPDATE Table1 SET (...) WHERE Column1='SomeValue' ELSE INSERT INTO Table1 VALUES (...) This approach does work, however it might not always be the best approach. This will do a table/index scan for both the SELECT statement and the UPDATE statement. In most standard approaches, the following statement will likely provide better performance. It will only perform one table/index scan instead of the two that are performed in the previous approach. UPDATE Table1 SET (...) WHERE Column1='SomeValue' IF @@ROWCOUNT=0 INSERT INTO Table1 VALUES (...) The saved table/index scan can increase performance quite a bit as the number of rows in the targeted table grows. Just remember, the examples in the MSDN documentation are usually the easiest way to implement something, not necessarily the best way. Also (as I re-learned recently), with any database operation, it is good to performance test the different approaches that you take. Sometimes the method that you think would be the worst might actually outperform the way that you think would be the better way.
Performance, SQL
Comments
jackhanbond 17 Feb 2008 11:31 PM # Thanks for the tip, I have a lot of code with the inferior approach that I will be updating. Fortunately, SQL 2008's Merge statement will make this a non-issue.
Jeremiah.Clark 18 Feb 2008 3:53 PM # Sent to me by Chris: "Since I don't have a blog and you don't allow anonymous comments I thought I'd shoot a quick email with a question/concern. Regarding your post "SQL: If Exists Update Else Insert" with the alternative method of doing the Update and then checking the @@ROWCOUNT as to whether to perform an insert or not... I definitely would not have thought of it that way either. However, I was wondering, with the scope of @@ROWCOUNT being global is there the possibility that the @@ROWCOUNT value could be incorrect within the local scope if there is heavy use on the database? Or am I incorrect on the scope being global? The reason I thought of this goes back to the use of SCOPE_IDENTITY() over @@IDENTITY to get the last identity in the same scope. Thanks for your time."
Jeremiah.Clark 18 Feb 2008 4:11 PM # I have enabled anonymous comments. I thought that I had done that before, but I guess not. Chris, Great question! The scope of @@ROWCOUNT (or ROWCOUNT_BIG() in the case of a VERY large result) is limited to the current scope that contains the statement that was previously executed. So you are guaranteed the correct result when using @@ROWCOUNT. Like you mentioned, this is not the case with @@IDENTITY. You can get some really unexpected results if it is used improperly. Jeremiah
Andrew Herron 21 Feb 2008 12:37 PM # Will this code work for any SQL compliant server?
Jeremiah.Clark 21 Feb 2008 2:19 PM # Andrew, The basic idea should work with other types of SQL servers (however, I have not verified this). You should just be able to use the @@ROWCOUNT equivalent for the system that you are using. For example: MySql uses "row_count()"
Guy 21 Feb 2008 2:26 PM # If you are thinking of MySQL there is a function called ROW_COUNT() that serves the same purpose (available as of version 5). Theoretically Jeremiah's suggestion should result in improved performance on MySQL also, but you should test it to make sure.
Richard Ayotte 21 Feb 2008 2:42 PM # MySQL does something much better. It's not part of the standard but still very useful. REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [(col_name,...)] VALUES ({expr | DEFAULT},...),(...),... It does what you describe. If the record exists, it is updated, else inserted. http://dev.mysql.com/doc/refman/5.0/en/replace.html
Jeremiah.Clark 21 Feb 2008 2:53 PM # Richard, Thanks for the comment. I was not aware of the REPLACE statement in MySQL.
Looking at the documentation, it does effectively do the same thing. But it seems to do it in a different manner. If a row with the same PK or UNIQUE index exists, it deletes the old row and then inserts the new row. For anything that does not already exist in the table, it inserts. I don't know if the deleting is more or less efficient than doing an update in MySQL. I would advise trying both ways and then compare the performance to see which solution better fits your needs.
Este tema an no ha recibido ninguna valoracin - Valorar este tema Un procedimiento almacenado de SQL Server al que puede llamar es el que devuelve un parmetro de estado o resultado. Se usa normalmente para indicar el funcionamiento correcto o incorrecto del procedimiento almacenado. El Controlador JDBC de Microsoft para SQL Server proporciona la clase SQLServerCallableStatement, que puede usar para llamar a este tipo de procedimiento almacenado y procesar los datos que devuelve. Al llamar a este tipo de procedimiento almacenado mediante el controlador JDBC, debe usar la secuencia de escape call de SQL junto con el mtodo prepareCall de la claseSQLServerConnection. La sintaxis para la secuencia de escape call con un parmetro de estado de devolucin es la siguiente: {[?=]call procedure-name[([parameter][,[parameter]]...)]}
Nota
Para obtener ms informacin acerca de las secuencias de escape de SQL, consulte Usar secuencias de escap
Al crear la secuencia de escape call especifique el parmetro de estado de devolucin mediante el carcter ? (signo de interrogacin). Este carcter acta como un marcador de posicin para el valor del parmetro que devolver el procedimiento almacenado. Para especificar un valor para un parmetro de estado de devolucin, debe especificar el tipo de datos del parmetro mediante el mtodo registerOutParameter de la clase SQLServerCallableStatement antes de ejecutar el procedimiento almacenado.
Nota
Al usar el controlador JDBC con una base de datos de SQL Server, el valor especificado para el parmetro de mtodo registerOutParametersiempre es un entero, que se puede especificar mediante el tipo de datos java.
Adems, al pasar un valor al mtodo registerOutParameter para un parmetro de estado de devolucin, debe especificar no solo los tipos de datos usados para el parmetro, sino tambin la posicin ordinal del parmetro en la llamada al procedimiento almacenado. En el caso del parmetro de estado de devolucin, su posicin ordinal siempre es 1 debido a que es siempre el primer parmetro de la llamada al procedimiento almacenado. Aunque la clase SQLServerCallableStatement proporciona la compatibilidad para utilizar el nombre del parmetro para indicar el parmetro concreto, puede utilizar el nmero de la posicin ordinal de solo un parmetro para los parmetros de estado de retorno. Cree, a modo de ejemplo, el siguiente procedimiento almacenado en la base de datos de ejemplo AdventureWorks de SQL Server 2005: CREATE PROCEDURE CheckContactCity (@cityName CHAR(50)) AS BEGIN IF ((SELECT COUNT(*) FROM Person.Address WHERE City = @cityName) > 1) RETURN 1 ELSE RETURN 0 END Este procedimiento almacenado devuelve un valor de estado de 1 0 en funcin de si la ciudad especificada en el parmetro cityName se encuentra en la tabla Person.Address. En el siguiente ejemplo, se pasa una conexin abierta a la base de datos de ejemplo AdventureWorks a la funcin y se usa el mtodo execute para llamar al procedimiento almacenado CheckContactCity: Java public static void executeStoredProcedure(Connection con) { try { CallableStatement cstmt = con.prepareCall("{? = call dbo.CheckContactCity(?)}"); cstmt.registerOutParameter(1, java.sql.Types.INTEGER); cstmt.setString(2, "Atlanta"); cstmt.execute(); System.out.println("RETURN STATUS: " + cstmt.getInt(1)); cstmt.close(); } catch (Exception e) { e.printStackTrace(); } }
Vea tambi
Pregunta
0
Inicie sesin para votar
Hola comunidad!!! Estoy trabajando con SQLServer 2008 Express y me gustara saber si pudieran orientarme en base a lo que quiero hacer. Necesito crear un Stored Procedure que inserte un valor y devuelva dos (el ID del registro de la tabla (@@Identity) y un codigo armado. La estructura de mi tabla es la siguiente: Tabla: Venta, Campos: idVEnta int not null, cliente varchar(50) not null, fecha date null, secuencia int null, sigla nvarchar(15) not null No se como hacer esto, no se se utilizar una funcion y un procedimiento que llame a esta funcin, usar dos procedimientos aparte (uno para insertar el registro y el otro para armar la cadena de codigo, o no se si en un solo stored porcedure se puede hacer esto. Lo que necesito es que al insertar la app me guarde el ID del registro insertado pero a la vez me devuelva la cadena de cdigo armada. A continuacin las dos instrucciones individuales: Instruccin para insertar: Declare @Fecha Date=GetDate(); Insert Into Venta Select 'Cliente200820131', @Fecha, Count(1)+1 From Venta WhereFecha=@Fecha; RETURN @@IDENTITY INSTRUCCION PARA ARMAR EL CODIGO select siglas +'-'+ convert(char(8), getdate(), 112) + '-' + cast(secuencial as varchar(12)) as codigo from ventas Qu se puede hacer en este caso? Gracias de antemano Saludos.
Respuestas
0
Inicie sesin para votar
Hola. Debes emplear parmetros de salida en un procedimiento almacenado. Deja el valor de retorno para gestionar estados de error del procedimiento. Si no sabes cmo, aqu tienes la referencia: http://technet.microsoft.com/es-es/library/ms187004(v=sql.105).aspx
Alberto Lpez Grande SQL Server MVP Visita mi blog en http://qwalgrande.com o Sgueme en twitter en http://twitter.com/qwalgrande Marcado como respuesta Alberto Lpez Grande (qwalgrande)MVP, Moderatorsbado, 14 de septiembre de
2013 18:43 sbado, 31 de agosto de 2013 8:25 Responder
| Citar |
Alberto Lpez Grande (qwalgrande) Plus Ultra Seguros (MVP) 58.370 Puntos
0
Inicie sesin para votar
Hola: Lo tendrias que hacer un procedimiento almacenado es la mejor forma, para eso fijate este link http://technet.microsoft.com/es-es/library/ms345415.aspx Al momento de traer la info, usas un SELECT para tu variable y el identity, ahora el @@Identity no es recomendable usar si no el SCOPE_IDENTITY, ya que el primero es el valor de un campo de identidad de una ultima insercin en toda las sesiones, en cambio el segundo solo retorna el valor del proceso que abarca el comando, te dejo un link donde te explican. http://technet.microsoft.com/es-es/library/ms187342.aspx Espero te ayude. Saludos Lincoln VS
sbado, 31 de agosto de 2013 7:10 Responder | Citar
0
Inicie sesin para votar
Hola. Debes emplear parmetros de salida en un procedimiento almacenado. Deja el valor de retorno para gestionar estados de error del procedimiento. Si no sabes cmo, aqu tienes la referencia: http://technet.microsoft.com/es-es/library/ms187004(v=sql.105).aspx
Alberto Lpez Grande SQL Server MVP Visita mi blog en http://qwalgrande.com o Sgueme en twitter en http://twitter.com/qwalgrande Marcado como respuesta Alberto Lpez Grande (qwalgrande)MVP, Moderatorsbado, 14 de septiembre de
2013 18:43 sbado, 31 de agosto de 2013 8:25 Responder | Citar |
Alberto Lpez Grande (qwalgrande) Plus Ultra Seguros (MVP) 58.370 Puntos
0
Inicie sesin para votar
Una vez que sepas como declarar una variable de salida en el procemiento almacenado, una forma fcil de halar n cantidad de parmetros hacia tu aplicacin es usar la variable output como varchar y luego concatenas todos los valores que necesitas en esa nica variable (usas un separador que no te d problemas: un guin, la coma, punto y coma...cualquiera que desees) y luego, desde donde la quieras utilizar, la separas por substring (si la trabajars desde la misma base de datos) o con un mid (si usas .net) o su equivalente en cualquier otro lenguaje. Saludos
Editado Jos Rolando sbado, 31 de agosto de 2013 16:10 sbado, 31 de agosto de 2013 16:09 Responder | Citar |
1
Inicie sesin para votar
Una vez que sepas como declarar una variable de salida en el procemiento almacenado, una forma fcil de halar n cantidad de parmetros hacia tu aplicacin es usar la variable output como varchar y luego concatenas todos los valores que necesitas en esa nica variable (usas un separador que no te d problemas: un guin, la coma, punto y coma...cualquiera que desees) y luego, desde donde la quieras utilizar, la separas por substring (si la trabajars desde la misma base de datos) o con un mid (si usas .net) o su equivalente en cualquier otro lenguaje.
Saludos
Esto es completamente inncesario, siendo que los procedimientos almacenados pueden tener mas de un parametro output sin problemas.
Blog
Obtener ID autonumerico insertado en SQL Server con ASP clasico
Recuperar la identidad de un registro recin insertado puede ser muy til si desea devolver el valor en el navegador o utilizarlo en una insercin o comando de actualizacin con el fin de crear o mantener una relacin entre dos o ms registros. Primero debe crear un Stored Procedure:
commInsert.ActiveConnection commInsert.CommandText commInsert.CommandType commInsert.CommandTimeout commInsert.Prepared commInsert.Parameters.Append 3, commInsert.Parameters.Append 200,_ commInsert.Parameters.Append 1,4,"123") commInsert.Execute() %>
Al programar en ASP clsico es recomendable usar Stored Procedures en SQL Server. Sin embargo, si no le es posible crear un SP entonces puede hacerse directamente desde ASP clsico:
<% strSQL = "SET NOCOUNT ON INSERT INTO tblName(TextField, NumberField)_ VALUES('ABC', 123) SELECT @@IDENTITY AS NewID SET NOCOUNT OFF"
"Provider=SQLOLEDB.1;Password=YourPassword;Persist Info=True;_
ID=YourUserID;
Initial
Catalog=YourDB;Data
Source=YOUR_REMOTE_SERVER_NAME"
Set
commInsert
Server.CreateObject("ADODB.Connection") strConnection
commInsert.Execute(strSQL) rsNewID("NewID")
commInsert
Nothing
rsNewID
Nothing
El comando de insercin se ejecuta y la nueva identidad devuelta se almacena en la variable varNewID. Tenga en cuenta el SET NOCOUNT ON y OFF, a ambos lados del comando INSERT, esto es importante, el comando fallar sin ellos. Por Consultores en sistemas (07/08/2012 @ 14:24:14, en Programacion ASP clasico , 782 clicks.) Votar Comentar (0) Historico Imprimir
Tags: autonumerico en sql, server sql, sql server 2008, sql server 2005, sql base de datos, ejemplos base datos, sql server
Pgina Principal
VIERNES, 13 DE ENERO DE 2012
Definicin SCOPE_IDENTITY() es una funcin capaz de devolver el valor de la columna de identidad (llave, index, etc) recien insertada.
Implementacin Para llevar a cabo la implementacin de esta funcin tomaremos como ejemplo un caso en el cul un registro se guarda en dos tablas: una tabla de Clientes y otra de Monitoreo de Actividad.
Estructura de Tablas Clientes Cli_Id (int) (identidad) (NO NULL) Cli_Nombre (nvarchar(60)) (NO NULL) Cli_Direccion (nvarchar(50))(NULL) Cli_Telefono (nvarchar(30))(NULL) Cli_Email (nvarchar(30))(NULL)
Monitor Mon_Id (int) (identidad) (NO NULL) Mon_IdRegistro (int) (NO NULL) Mon_NombreTabla (nvarchar(50))(NO NULL)
Code-behind C# 01.//Variable de Conexin 02.SqlConnection con = new SqlConnection("Data Source=USER\\SQLEXPRESS;Initial Catalog=basePrueba;Integrated Security=True"); 03.con.Open(); 04. 05.//Variable que contendr el valor de la columna de identidad devuelto por la funcin SCOPE_IDENTITY() 06.int idRegistro = 0; 07. 08.//Armo el Query para Clientes 09.//A la hora de declarar el query agrego la funcin SCOPE_IDENTITY() 10.SqlCommand cmd = new SqlCommand("INSERT INTO Clientes " + 11."(Cli_Nombre, Cli_Direccion, Cli_Telefono, Cli_Email) " + 12."VALUES" + 13."(@nombre, @direccion, @telefono, @email) " + 14."SELECT SCOPE_IDENTITY()", con); 15. 16.cmd.Parameters.Add("@nombre", SqlDbType.NVarChar).Value = txtNombre.Text; 17.cmd.Parameters.Add("@direccion", SqlDbType.NVarChar).Value = txtDireccion.Text; 18.cmd.Parameters.Add("@telefono", SqlDbType.NVarChar).Value = txtTelefono.Text; 19.cmd.Parameters.Add("@email", SqlDbType.NVarChar).Value = txtEmail.Text; 20. 21.//Ejecuto la consulta y obtengo el valor devuelto por la misma 22.idRegistro = Convert.ToInt32(cmd.ExecuteScalar()); 23. 24.//Armo Query para el Monitor de Actividades 25.//En la consulta paso un parmetro con el valor obtenido de la consulta anterior
26.cmd.CommandText = "INSERT INTO Monitor " + 27."(Mon_IdRegistro, Mon_NombreTabla) " + 28."VALUES" + 29."(@idRegistro, @nombreTabla)"; 30. 31.cmd.Parameters.Add("@idRegistro", SqlDbType.Int).Value = idRegistro; 32.cmd.Parameters.Add("@nombreTabla", SqlDbType.NVarChar).Value = "Clientes"; 33. 34.con.Close();
VB.NET 01.'Variable de Conexin 02.Dim con As New SqlClient.SqlConnection("Data Source=USER\\SQLEXPRESS;Initial Catalog=basePrueba;Integrated Security=True") 03.con.Open() 04. 05.'Variable que contendr el valor de la columna de identidad devuelto por la funcin SCOPE_IDENTITY() 06.Dim idRegistro As Integer = 0 07. 08.'Armo el Query para Clientes 09.'A la hora de declarar el query agrego la funcin SCOPE_IDENTITY() 10.Dim cmd As New SqlClient.SqlCommand("INSERT INTO Clientes " _ 11.& "(Cli_Nombre, Cli_Direccion, Cli_Telefono, Cli_Email) " _ 12.& "VALUES" _ 13.& "(@nombre, @direccion, @telefono, @email) " _ 14.& "SELECT SCOPE_IDENTITY()", con) 15. 16.cmd.Parameters.Add("@nombre", SqlDbType.NVarChar).Value = txtNombre.Text
17.cmd.Parameters.Add("@direccion", SqlDbType.NVarChar).Value = txtDireccion.Text 18.cmd.Parameters.Add("@telefono", SqlDbType.NVarChar).Value = txtTelefono.Text 19.cmd.Parameters.Add("@email", SqlDbType.NVarChar).Value = txtEmail.Text 20. 21.'Ejecuto la consulta y obtengo el valor devuelto por la misma 22.idRegistro = Convert.ToInt32(cmd.ExecuteScalar()) 23. 24.'Armo Query para el Monitor de Actividades 25.'En la consulta paso un parmetro con el valor obtenido de la consulta anterior 26.cmd.CommandText = "INSERT INTO Monitor " _ 27.& "(Mon_IdRegistro, Mon_NombreTabla) " _ 28.& "VALUES" _ 29.& "(@idRegistro, @nombreTabla)" 30. 31.cmd.Parameters.Add("@idRegistro", SqlDbType.Int).Value = idRegistro 32.cmd.Parameters.Add("@nombreTabla", SqlDbType.NVarChar).Value = "Clientes" 33. 34.con.Close()
Seudocdigo 1. Declaro variable de conexin y le asigno un Connection String 2. Abro la Conexin 3. Declaro la variable 'idRegistro' que contendr el valor de la columna de identidad del registro recin insertado 4. Declaro variable Command y le asigno un CommandText --CommandText: Insertar en Clientes: en los campos (campos) los valores (valores) y seleccionar el valor del campo de identidad 5. Agrego los parmetros necesarios 6. Ejecuto la consulta y obtengo el valor solicitado 7. Asigno CommandText --CommandtText: Insertar en Monitor: en los campos (campos) los valores (valores) 8. Agrego parmetros necesarios --Parametro 'idRegistro': lo igualo al valor obtenido en la consulta anterior. 9. Ejecuto el query 10. Cierro la conexin
Publicadas por Santiago Ezequiel Rueda a la/s 2:08 Enviar esto por correo electrnicoBlogThis!Compartir en TwitterCompartir en FacebookCompartir en Pinterest Etiquetas: SQL Server, Transact-SQL
12 comentarios:
1. Fajgri Isa Espinoza19 de enero de 2012, 2:43 y como lo gurdo en la otra tabla Responder Respuestas
1.
Santiago Ezequiel Rueda19 de enero de 2012, 12:17 Buenos das Isa. Como vers el valor de la columna de identidad de guarda en la variable "idRegistro". Seguidamente utilizamos el valor de esta variable para insertar el registro en la otra tabla, como lo muestra el ejemplo. Primero se inserta un registro en la tabla de Clientes y se obtiene el ID del mismo, luego se inserta un registro en la tabla de Monitor de Actividades. Saludos. Responder
Personas que lo han encontrado til: 4 de 5 - Valorar este tema Proporciona el resto de un nmero dividido entre otro.
Sintaxis
dividend % divisor
Argumentos
dividend
La expresin numrica que se va a dividir. El valor de dividend puede ser cualquier expresin vlida de MicrosoftSQL Server Compact perteneciente a la categora de tipos de datos enteros.
divisor
La expresin numrica entre la que se va a dividir el dividendo. El valor de divisorpuede ser cualquier expresin vlida de SQL Server perteneciente a cualquier tipo de datos de la categora de tipos de datos enteros.
Tipos de resultado
int
Ejemplo de cdigo
En el ejemplo siguiente se utiliza la instruccin modulo para identificar a aquellos empleados cuyos valores de EmployeeID son nmeros pares. SELECT EmployeeID, LastName, EmployeeID % 2 FROM Employees WHERE EmployeeID % 2 = '0' ste es el conjunto de resultados: EmployeeID LastName #2 ------------------2 Funk 0 4 Pearson 0 6 Sutton 0 8 Calafato 0
Obtener columnas del registro q tiene el campo con valor mximo. max()
Foros de Acceso a Datos > SQL Server
Pregunta
0
Inicie sesin para votar
Hola amigos, tengo la siguiente inquietud: Es posible usando el estandar de sql o con transact SQL, obtener las dems columnas de un registro que cumple la condicin max() y group by, sin utilizar joins Actualmente estoy desarrollado la siguiente consulta y quiero saber si puedo optimizarla sin necesidad de usar Join:
Cdigo : SELECT T.nombreID, T.cualidad, maxPer.maxPeriodo FROM T INNER JOIN ( select nombreID, max(periodo) as maxPeriodo from T where estado =1 group by nombreID ) as maxPer ON maxPer.maxPeriodo = T.periodo and maxPer.nombreID= T.nombreID En este momento estoy desarrollando en SQLServer 2005. o Agradezco sus ideas y comentarios. Editado charJ lunes, 31 de enero de 2011 15:47
lunes, 31 de enero de 2011 15:15 Responder | Citar
charJ 0 Puntos
Respuestas
0
Inicie sesin para votar
Por ejemplo:
;WITH cte AS (SELECT nombreId, cualidad, periodo, ROW_NUMBER OVER (PARTITION BY nombreID ORDER BY periodo DESC) AS rn FROM T WHERE estado = 1) SELECT nombreId, cualidad, periodo FROM cte WHERE rn = 1
Pero revisa el plan de ejecucin de ambas consultas para ver cul es efectivamente ms eficiente o o o o o o
Propuesto como respuesta Carlos Sacristan lunes, 31 de enero de 2011 15:27 Votado como til charJ lunes, 31 de enero de 2011 15:39 Propuesto como respuesta Willy TaverasModerator lunes, 31 de enero de 2011 16:30 Votado como til charJ lunes, 31 de enero de 2011 16:40 Propuesto como respuesta HunchbackMVP lunes, 31 de enero de 2011 20:13 Marcado como respuesta Alberto Lpez Grande (qwalgrande)MVP, Moderatorlunes, 31 de enero de 2011 20:43 lunes, 31 de enero de 2011 15:26 Responder | Citar |
Carlos Sacristan
0
Inicie sesin para votar
Por ejemplo:
;WITH cte AS (SELECT nombreId, cualidad, periodo, ROW_NUMBER OVER (PARTITION BY nombreID ORDER BY periodo DESC) AS rn FROM T WHERE estado = 1) SELECT nombreId, cualidad, periodo FROM cte WHERE rn = 1
Pero revisa el plan de ejecucin de ambas consultas para ver cul es efectivamente ms eficiente o o o o o o
Propuesto como respuesta Carlos Sacristan lunes, 31 de enero de 2011 15:27 Votado como til charJ lunes, 31 de enero de 2011 15:39 Propuesto como respuesta Willy TaverasModerator lunes, 31 de enero de 2011 16:30 Votado como til charJ lunes, 31 de enero de 2011 16:40 Propuesto como respuesta HunchbackMVP lunes, 31 de enero de 2011 20:13 Marcado como respuesta Alberto Lpez Grande (qwalgrande)MVP, Moderatorlunes, 31 de enero de 2011 20:43 lunes, 31 de enero de 2011 15:26 Responder | Citar |
0
Inicie sesin para votar
Gracias. Pero en la consulta que expones supones todos los registros como si fueran un solo grupo y tomas el primero. La idea es traer las columnas del registro mximo agrupado por el campo nombreID.
lunes, 31 de enero de 2011 15:33 Responder | Citar |
charJ 0 Puntos
0
Inicie sesin para votar
No entiendo tu comentario. Has comprobado que los resultados son diferentes entre tu query y la que propuse yo?
lunes, 31 de enero de 2011 16:28 Responder | Citar |
0
Inicie sesin para votar
Se debe obtener el mximo <periodo> para cada <nombreID> en donde el estado sea igual a 1. Y del periodo obtenido para cada nombreId se debe obtener la <cualidad>; de tal forma que el resultado obtenido ser:
INNER JOIN ( select nombreID, max(periodo) as maxPeriodo from T where estado =1 group by nombreID ) as maxPer ON maxPer.maxPeriodo = T.periodo and maxPer.nombreID= T.nombreID
charJ 0 Puntos
0
Inicie sesin para votar
Hola. Coincido con Carlos, la consulta que l ha expuesto es tal t la has especificado. Si hay algn error (salvo quiz ponerle los "()" tras ROW_NUMBER), a m tambin se me escapa. Otra cosa es que sea mejor que la que ya tienes, que tengo mis dudas. Para eso, nada como evaluar las lecturas lgicas que hace cada una. Qu nmero de lecturas lgicas se obtienen en cada caso? Para mostrar las lecturas lgicas, ejecuta "set statistics io on", luego lanza cada consulta. Djanos saber qu se retorna en cada caso.
Responder | Citar |
Alberto Lpez Grande (qwalgrande) Plus Ultra Seguros (MVP) 58.370 Puntos
0
Inicie sesin para votar
Hola. Muchas gracias a todos por su tiempo y las respuestas. Realizando la prueba sobre la tabla de datos T expuesta anteriormente, se obtuvieron las siguientes lecturas para cada consulta:
1. SELECT T.nombreID, T.cualidad, maxPer.maxPeriodo FROM T INNER JOIN ( select nombreID, max(periodo) as maxPeriodo from T where estado =1 group by nombreID ) as maxPer ON maxPer.maxPeriodo = T.periodo and maxPer.nombreID= T.nombreID
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table 'T'. Scan count 2, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
2. ;WITH cte AS (SELECT nombreId, cualidad, periodo, ROW_NUMBER () OVER (PARTITION BY nombreID ORDER BY periodo DESC) AS rn FROM T WHERE estado = 1) SELECT nombreId, cualidad, periodo FROM cte WHERE rn = 1 LECTURAS OBTENIDAS (3 filas afectadas) Table 'T'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Al parecer es mas eficiente la segunda opcin. Muchas gracias.
charJ 0 Puntos
Hola. Ojo, si la tabla tiene 3 registros (o 3.000), la opcin de estas opciones de agregado es muy til. Pero si tienes millones, la cosa puede cambiar.
RETURN (Transact-SQL)
SQL Server 2012 Otras versiones
Personas que lo han encontrado til: 2 de 3 - Valorar este tema Sale incondicionalmente de una consulta o procedimiento. RETURN es inmediata y completa, y se puede utilizar en cualquier punto para salir de un procedimiento, lote o bloque de instrucciones. Las instrucciones que siguen a RETURN no se ejecutan. Convenciones de sintaxis de Transact-SQL
Sintaxis
RETURN [ integer_expression ]
Argumentos
integer_expression Es el valor entero que se devuelve. Los procedimientos almacenados pueden devolver un valor entero al procedimiento que realiza la llamada o a una aplicacin.
Nota
A menos que se documente de otra manera, todos los procedimientos almacenados del sistema devuelven el v valor distinto de cero indica que se ha producido un error.
Comentarios
Cuando se utiliza con un procedimiento almacenado, RETURN no puede devolver un valor NULL. Si un procedimiento intenta devolver un valor NULL (por ejemplo, al utilizar RETURN @status cuando @status es NULL), se genera un mensaje de advertencia y se devuelve un valor 0. El valor de estado devuelto se puede incluir en las siguientes instrucciones Transact-SQL del lote o procedimiento que ha ejecutado el procedimiento actual, pero se debe escribir de la forma siguiente: EXECUTE @return_status = <procedure_name>.
Ejemplos
SELECT 'Return Status' = @return_status; GO El conjunto de resultados es el siguiente. Return Status ------------2 Ejecute la consulta de nuevo con otro nmero de contacto. DECLARE @return_status int EXEC @return_status = checkstate '12345678901'; SELECT 'Return Status' = @return_status; GO El conjunto de resultados es el siguiente. Return Status ------------2
Vea tambin
Referencia
ALTER PROCEDURE (Transact-SQL) CREATE PROCEDURE (Transact-SQL) DECLARE @local_variable (Transact-SQL) EXECUTE (Transact-SQL) SET @local_variable (Transact-SQL)
Te ha resultado til? S No
Adiciones de comunidad
AGREGAR
| Marcas registrada |
SQL: Cmo obtener la primera y la ltima fila de los registros de una consulta
En el mundo de la programacin y el desarrollo de aplicaciones, a veces nos pasa que queremos hacer algo muy sencillo pero no recordamos cmo hacerlo. Pues bien, a m me ha pasado algo parecido, as que os lo voy a comentar con un breve ejemplo por si a alguien ms le pasa, espero que os sirva de ayuda.
A continuacin os indico las sentencias SQL generadas para obtener la primera y ltima fila de una tabla, probados con SQL Server. Para el ejemplo he generado una pequea tabla de Pedidoscon los campos: ID del pedido Descripcin del pedido Fecha del pedido Cliente Direccin de entrega de dicho pedido.
Primer registro: Utilizamos ordenacin Ascendente (ASC). SELECT TOP 1 * FROM Pedido ORDER BY Fecha ASC ltimo registro: Utilizamos ordenacion Descencente (DESC), para obtener los resultados en orden inverso. SELECT TOP 1 * FROM Pedido ORDER BY Fecha DESC
) UNION SELECT (
SELECT TOP 1 * FROM Pedido ORDER BY Fecha DESC ) El resultado sera el siguiente: