Hola gente!, en esta ocasión les voy a comentar una datito interesante con respecto a MSSQL Server 2K5. Como ya sabemos ahora el acceso y modificación a tablas de sistema esta restringido, todo se realiza a través de vistas y stored procedures, por ejemplo y viene al caso la tabla sys.columns que en versiones anteriores es syscolumns, bueno, vamos a lo concreto, en estos momentos me encuentro desarrollando un proceso de migración de datos entre un MSSQLServer 7.0 SP4 y MSSQL2K5 SP1, en dicho desarrollo necesitaba obtener datos de la vista sys.columns y sys.column_type_usages, con sys.columns no tuve problemas pero con la vista sys.column_type_usages sí, pues estaba buscando una registro donde el campo utype sea < 256.
Si realizamos un sp_helptext ‘sys.column_type_usages’ veremos que la vista se encuentra definida de la siguiente manera:
CREATE VIEW sys.column_type_usages AS
SELECT id AS object_id,
colid AS column_id,
utype AS user_type_id
FROM sys.syscolpars
WHERE number = 0 AND utype > 256
Como muestra la definición de la vista, esta hace referencia a sys.syscolpars, si nosotros realizamos la siguiente consulta sin condiciones o filtro, nos da un error donde nos dice que el objeto no existe.
select * from sys.syscolpars
Msg 208, Level 16, State 1, Line 1
Invalid object name 'sys.syscolpars'.
Como hacemos para acceder a ese dato ?
Debemos recordar que existe una nueva base de datos llamada ‘mssqlsystemresource’ donde contiene todos los objetos de sistema como por ej: sys.objects que aparece en cada base de datos dentro del esquema sys.
Microsoft recomienda que a esta base de datos solo acceda personal de Microsoft Customer Support Services (CSS), pero en este caso y la vista al no satisfacer el requerimiento, no nos quedo otra alternativa que acceder y buscar el dato.
Procedimos a bajar el motor de base de datos y luego a levantarlo en single_user_mode, con la siguiente sentencia:
C:\MSSQL.1\MSSQL\Binn\sqlservr.exe -sMSSQLServer –m
Luego vía query analizer ejecutamos la consulta con éxito.
use mssqlsystemresource
go
select name,id,utype from sys.syscolpars where xtype =189
name id utype
-------------------- ----------- -----------
incremental_timestam 596959306 189
@timestamp 533452507 189
@timestamp 233465586 189
(3 row(s) affected)
Espero les sirva, mas que nada, cuando tengan que consultar datos de sistema que no estén dentro de las vistas dadas en esta versión de SQL Server 2K5.
Abrazo virtual y hasta la próxima.
Que tal como están ?, con ganas de leer un poco sobre MS SQL Server, bueno bárbaro pasemos a lo concreto.
Hoy les voy a comentar una particularidad entre las sentencias ‘TRUNCATE TABLE’ y ‘DELETE’ para eliminar datos entre tablas con integridad referencial. Escenario: Nos han solicitado realizar una migración de datos entre bases de usuario donde los dbms son los reconocidos MSSQL70 y MSSQL2K5, donde el origen de datos es el SQL70 y el destino es un SQL2K5. Este proceso se lleva a cabo con los chequeos de datos a migrar, backup, inhabilitacion de constraints , FK, Triggers y chequeos posteriores a la migración. Cabe destacar la complejidad del mismo pues, no se realiza solo para un motor en particular sino para diversas bases de datos, sin utilizar SSIS ni SMO, sino todo a través de TSQL y command script (cmd-windows batch) del OS. Todo el procedimiento es automático a través de script’s parametrizables. Dicho procedimiento actúa como una caja negra, en donde se le envían parámetros los procesa, genera script’s en base a información recolectada y los ejecuta.(Igualmente en otra ocasión explicare con mas detalles el procedimiento y presentare script’s de ejemplo, que les pueden llegar a resultar útiles).
Ya que tenemos una visión general del tema, les paso a explicar el problema resultante con la sentencia ‘TRUNCATE TABLE’ y la solución con ‘DELETE’.
Una vez inhabilitada la integridad referencial entre todas las tablas de la base en este caso ‘DB1‘ al querer realizar un TRUNCATE TABLE de una de las tablas que es referencia por otra nos surge el siguiente error:
Msg 4712, Level 16, State 1, Line 1
Cannot truncate table 'HumanResources.Employee' because it is being referenced by a FOREIGN KEY constraint.
Aparentemente la sentencia TRUNCATE TABLE no chequea la inhabilitación de los CONTRAINT FK. Como solucionamos esto?, utilizando la sentencia DELETE que si realiza este control y elimina los datos correctamente.
Más adelante les explicare porque siempre trato de Utilizar la sentencia truncate y no delete.
Bueno espero que les sirva y les mando un abrazo virtual a todos.
JuanPL
Link's relacionados:
http://www.todosql.com/blog/200703/truncate-table-vs-delete
Hola!, como están!, como los trata la vida!
Hoy quería comentarles algo que seguramente les resulte útil, mas que nada a los desarrolladores, que posiblemente no estén tan familiarizados con el Log transaccional de la base de datos.
Un error muy común en las transacciones que modifican o agregan datos sobre las tablas de una base, es el siguiente:
SQLState = 37000, NativeError = 9002
Error = [Microsoft][ODBC SQL Server Driver][SQL Server]The log file for database
'mibase’ is full. Back up the transaction log for the database to free up some log space.
Si están realizando un ‘delete’ sobre tablas sin condición o filtro, en vez de utilizar esta sentencia deben realizar un ‘truncate table’, pues esta sentencia no escribe el transaction log de la base, por ende, no les traera aparejado el problema anterior.
En cambio con las sentencias insert, update traten de utilizar, conjuntos registros (recordset) mas pequeños trabajando via codigo como VB.net con transacciones explicitas, por ej:OleDbConnection.BeginTransaction (), o si bien puro SQL con commit mas seguidos y con funciones del tipo rowcount (ver book's de SQL Server: set rowcount).
Y como siempre…, abrazo virtual para todos.
JuanPL
Link's relacionados:
http://www.todosql.com/blog/200703/particularidad-entre-las-sentencias-t...
Hola que tal!, como estan?, les cuento que estoy un poco mejor con respecto a el inconveniente que tuve días atrás y de a poco todo se va equilibrando.
Bueno quería compartir este pequeño script que es para detectar registros duplicados y es aplicable para mssql2k5,mssql2k,mssql70,mssql65 y otros motores de base de datos como db2, oracle, etc, debido a que es ansi sql. Este puede ser de gran utilidad por alguna falla en las aplicaciones por lo cual necesitemos depurar o bien determinar que registros son duplicados.
Script:
SELECT c1,c2 FROM MiTabla
GROUP BY c1,c2
HAVING count(*) > 1
Bueno hoy fue cortito y como siempre un abrazo virtual para todos.
Que tal!, hoy les voy a contar una solicitud que tuve con respecto a la cardinalidad de tablas en MSSQLServer2000.
Les paso a contar, necesitábamos obtener la cardinalidad y tamaño de 15000 tablas de una app. que posee módulos de RRHH y Finanzas muy conocido en el mercado, porque?, pues estábamos teniendo problemas de performance y una de las medidas iniciales era informar a la analista de la aplicación, cuales eran las tablas mas grandes tanto en cantidad de registros como en tamaño en MB y de esta manera encarar una depuración de tablas (siempre y cuando fuera factible ) para evitar table scan, búsquedas en indices, join’s, demasiados costosos a nivel disco, ram y procesador.
No solo nos sirvió para encarar el problema de performance, sino también para tener una estadística de crecimiento de las tablas.
Uds. se preguntaran cual es el problema? , bueno, el resultado lo necesitábamos en una tabla con campos conteniendo, tanto, ROWS como MB, imagínense ustedes, al tratarse de 15000 tablas, no puede hacerse por el enterprise manager o administrador corporativo, en tanto si puede hacerse con el sp_spaceused, pero editándolo para que la info que nos devuelva la almacenemos en KB y ROWS y luego directamente realicemos la consulta vía stored procedure que realice el calculo a MB.
Para ello, fue necesario realizarlo vía script’s, pues, deben ser 15000 líneas de ejecución y luego editar el sp_spaceused y crear un sp_spaceused2.
A continuación les describo un poco de código:
Modificación de stored procedure sp_spaceused a sp_spaceused2
use master
go
--Crea Stored para ver tamaño en KB
create procedure sp_spaceused2 --- 1996/08/20 17:01
@objname nvarchar(776) = null, -- The object we want size on.
@updateusage varchar(5) = false -- Param. for specifying that
-- usage info. should be updated.
as
declare @id int -- The object id of @objname.
declare @type character(2) -- The object type.
declare @pages int -- Working variable for size calc.
declare @dbname sysname
declare @dbsize dec(15,0)
declare @logsize dec(15)
declare @bytesperpage dec(15,0)
declare @pagesperMB dec(15,0)
/*Create temp tables before any DML to ensure dynamic
** We need to create a temp table to do the calculation.
** reserved: sum(reserved) where indid in (0, 1, 255)
** data: sum(dpages) where indid < 2 + sum(used) where indid = 255 (text)
** indexp: sum(used) where indid in (0, 1, 255) - data
** unused: sum(reserved) - sum(used) where indid in (0, 1, 255)
*/
create table #spt_space
(
rows int null,
reserved dec(15) null,
data dec(15) null,
indexp dec(15) null,
unused dec(15) null
)
/*
** Check to see if user wants usages updated.
*/
if @updateusage is not null
begin
select @updateusage=lower(@updateusage)
if @updateusage not in ('true','false')
begin
raiserror(15143,-1,-1,@updateusage)
return(1)
end
end
/*
** Check to see that the objname is local.
*/
if @objname IS NOT NULL
begin
select @dbname = parsename(@objname, 3)
if @dbname is not null and @dbname <> db_name()
begin
raiserror(15250,-1,-1)
return (1)
end
if @dbname is null
select @dbname = db_name()
/*
** Try to find the object.
*/
select @id = null
select @id = id, @type = xtype
from sysobjects
where id = object_id(@objname)
/*
** Does the object exist?
*/
if @id is null
begin
raiserror(15009,-1,-1,@objname,@dbname)
return (1)
end
if not exists (select * from sysindexes
where @id = id and indid < 2)
if @type in ('P ','D ','R ','TR','C ','RF') --data stored in sysprocedures
begin
raiserror(15234,-1,-1)
return (1)
end
else if @type = 'V ' -- View => no physical data storage.
begin
raiserror(15235,-1,-1)
return (1)
end
else if @type in ('PK','UQ') -- no physical data storage. --?!?! too many similar messages
begin
raiserror(15064,-1,-1)
return (1)
end
else if @type = 'F ' -- FK => no physical data storage.
begin
raiserror(15275,-1,-1)
return (1)
end
end
/*
** Update usages if user specified to do so.
*/
if @updateusage = 'true'
begin
if @objname is null
dbcc updateusage(0) with no_infomsgs
else
dbcc updateusage(0,@objname) with no_infomsgs
print ' '
end
set nocount on
/*
** If @id is null, then we want summary data.
*/
/* Space used calculated in the following way
** @dbsize = Pages used
** @bytesperpage = d.low (where d = master.dbo.spt_values) is
** the # of bytes per page when d.type = 'E' and
** d.number = 1.
** Size = @dbsize * d.low / (1048576 (OR 1 MB))
*/
if @id is null
begin
select @dbsize = sum(convert(dec(15),size))
from dbo.sysfiles
where (status & 64 = 0)
select @logsize = sum(convert(dec(15),size))
from dbo.sysfiles
where (status & 64 <> 0)
select @bytesperpage = low
from master.dbo.spt_values
where number = 1
and type = 'E'
select @pagesperMB = 1048576 / @bytesperpage
select database_name = db_name(),
database_size =
ltrim(str((@dbsize + @logsize) / @pagesperMB,15,2) + ' MB'),
'unallocated space' =
ltrim(str((@dbsize -
(select sum(convert(dec(15),reserved))
from sysindexes
where indid in (0, 1, 255)
)) / @pagesperMB,15,2)+ ' MB')
print ' '
/*
** Now calculate the summary data.
** reserved: sum(reserved) where indid in (0, 1, 255)
*/
insert into #spt_space (reserved)
select sum(convert(dec(15),reserved))
from sysindexes
where indid in (0, 1, 255)
/*
** data: sum(dpages) where indid < 2
** + sum(used) where indid = 255 (text)
*/
select @pages = sum(convert(dec(15),dpages))
from sysindexes
where indid < 2
select @pages = @pages + isnull(sum(convert(dec(15),used)), 0)
from sysindexes
where indid = 255
update #spt_space
set data = @pages
/* index: sum(used) where indid in (0, 1, 255) - data */
update #spt_space
set indexp = (select sum(convert(dec(15),used))
from sysindexes
where indid in (0, 1, 255))
- data
/* unused: sum(reserved) - sum(used) where indid in (0, 1, 255) */
update #spt_space
set unused = reserved
- (select sum(convert(dec(15),used))
from sysindexes
where indid in (0, 1, 255))
select reserved = ltrim(str(reserved * d.low / 1024.,15,0) +
' ' + 'KB'),
data = ltrim(str(data * d.low / 1024.,15,0) +
' ' + 'KB'),
index_size = ltrim(str(indexp * d.low / 1024.,15,0) +
' ' + 'KB'),
unused = ltrim(str(unused * d.low / 1024.,15,0) +
' ' + 'KB')
from #spt_space, master.dbo.spt_values d
where d.number = 1
and d.type = 'E'
end
/*
** We want a particular object.
*/
else
begin
/*
** Now calculate the summary data.
** reserved: sum(reserved) where indid in (0, 1, 255)
*/
insert into #spt_space (reserved)
select sum(reserved)
from sysindexes
where indid in (0, 1, 255)
and id = @id
/*
** data: sum(dpages) where indid < 2
** + sum(used) where indid = 255 (text)
*/
select @pages = sum(dpages)
from sysindexes
where indid < 2
and id = @id
select @pages = @pages + isnull(sum(used), 0)
from sysindexes
where indid = 255
and id = @id
update #spt_space
set data = @pages
/* index: sum(used) where indid in (0, 1, 255) - data */
update #spt_space
set indexp = (select sum(used)
from sysindexes
where indid in (0, 1, 255)
and id = @id)
- data
/* unused: sum(reserved) - sum(used) where indid in (0, 1, 255) */
update #spt_space
set unused = reserved
- (select sum(used)
from sysindexes
where indid in (0, 1, 255)
and id = @id)
update #spt_space
set rows = i.rows
from sysindexes i
where i.indid < 2
and i.id = @id
select name = object_name(@id),
rows = convert(char(11), rows),
reserved = ltrim(str(reserved * d.low / 1024.,15,0)),
CONVERT(CHAR(8), GETDATE(),112) as fecha,
'KB' as tipo
from #spt_space, master.dbo.spt_values d
where d.number = 1
and d.type = 'E'
end
return (0) -- sp_spaceused2
GO
--sp_spaceused2
--**************************FIN*******************************************
2) Creamos una tabla llamada Cardinalidad para contener la info.
USE MiBase
GO
CREATE TABLE Cardinalidad (nombre varchar(50), tamaño int,fecha varchar(8),tipo char(4)DEFAULT 'MB')
GO
3) Ejecutamos el siguiente query:
SELECT 'INSERT INTO Cardinalidad EXEC sp_spaceused2 '+ name FROM sysobjects WHERE xtype ='U'
GO
4) La salida del paso anterior, la volvemos a ejecutar, por ej:
INSERT INTO Cardinalidad EXEC sp_spaceused2 Orders
INSERT INTO Cardinalidad EXEC sp_spaceused2 Products
INSERT INTO Cardinalidad EXEC sp_spaceused2 Order Details
INSERT INTO Cardinalidad EXEC sp_spaceused2 CustomerCustomerDemo
INSERT INTO Cardinalidad EXEC sp_spaceused2 CustomerDemographics
.
.
.
Hasta la tabla 15000.
5) Luego creamos un stored procedure que realice la consulta y trasforme los KB a MB.
CREATE PROCEDURE TamañoTablasEnMB
@nombre as VARCHAR(255)
as
IF @nombre IS NOT NULL
BEGIN
SELECT nombre,(tamaño)/1024 as 'Tamaño en MB',fecha FROM Cardinalidad
WHERE tamaño > 1035 AND nombre = @nombre
ORDER BY 'Tamaño en MB' DESC
END
ELSE
BEGIN
SELECT nombre,(tamaño)/1024 as 'Tamaño en MB',fecha FROM Cardinalidad
WHERE tamaño > 1035
ORDER BY 'Tamaño en MB' DESC
END
Todo este proceso se automatizo por DTS package y el resultado se grabo en un archivo excel o renderizarlo via reporting services (en SQL2005 con SSIS y SSRS).
Una observacion: OJO con la cantidad de registros que almacenen en excel, pues, tiene un límite de 65536.
Y como siempre, un abrazo virtual para todos.
Como están hoy ?, les cuento que mi hija me esta llamando para comer (cena) así que luego continuo!…
Buenas !, ya termine de comer milanesas con papas fritas , riquísimo !!!.
Pasemos al aspecto técnico, siempre es conveniente trabajar con stored procedure’s, debido a los tiempos de respuesta/rendimiento/performance, pues, al realizar query´s AdHoc o consultas/sentencias generadas en el vuelo, el dbms que las recibe siempre las ve como nuevas y pierde tiempo en chequeo de sintaxis, compilación y generación de plan de ejecución entre otras tareas previas a la ejecución de la misma. En cambio con un sp (stored procedure) lo realiza una sola vez, hasta tanto no se reinicie el server o bien se recompile el sp, ya sea en forma explícita (Opción ‘with recompile’) o bien ante algún cambio en el código del mismo, que será compilado y guardado en el buffer cache del SQL Server. (Lo pueden llegar a observar con el contador buffer ‘cache hit ratio’ y levantando algún trace-profile auditando eventos de compilación y recompilacion de sentencias y verificar si poseen significantes compilaciones y recompilaciones).
Un ejemplo, sería una lecto-clasificadora de cheques de un banco o financiera, donde el tiempo de respuesta debe ser extremadamente rápido (tuve oportunidad de comprobarlo en la realidad, es mas, no nos quedo otra que realizarlo para no interferir con la operatoria normal de la entidad, pues sino el cambio tecnológico, hubiere resultado contraproducente).
A continuación les paso un poco de código:
Como llamamos a un stored procedure en forma remota ?
En SQLServer70 y SQLServer2000/MSSQLServer2K:
EXEC LinkedServer.BaseDatos.Owner.StoredProcedure ‘parametros’
EXEC servidorlinkeado.mibase.dbo. mi_procedimiento_almacenado ‘1’
En SQLServer2005/MSSQLServer2K5:
EXECUTE (‘mi_procedimiento_almacenado’) AT LinkedServer
Bueno gente me voy a dormir un poco.
Un abrazo virtual para todos y espero les sirva.
Gente !!! como están !!!, bueno les cuento una cortita, si necesitan restorear uno o varios log's transaccionales de varias bases de datos y cuyo backup es frecuente, por ej: 3 min y sin la intervención de un operador vía GUI ya sea para ejecutarlo o generar el script de ejecución; la manera de realizarlo es en modo batch ¿como?, bueno, a continuación les paso un stored procedure, el cual deben correrlo vía 'sqlcmd' y cuya salida nuevamente deben correrlo por esta herramienta, por lógica, todo deben realizarlo vía 'cmd'.
CREATE PROCEDURE sp_restorealog
@device varchar(255),
@base varchar(255)
AS
--Creo objetos y carga variable
SET NOCOUNT ON
DECLARE @@sentencia varchar(255)
SET @@sentencia = (SELECT 'RESTORE HEADERONLY FROM '+@device)
IF (SELECT name FROM sys.objects WHERE name ='headeronly') IS NOT NULL
DROP TABLE headeronly
CREATE TABLE headeronly (ca varchar(255),cb varchar(255),cc varchar(255),cd varchar(255),ce varchar(255),cf varchar(255),cg varchar(255),ch varchar(255),ci varchar(255),cj varchar(255),ck varchar(255),cl varchar(255),cm varchar(255),
cn varchar(255),co varchar(255),cp varchar(255),cq varchar(255),cr varchar(255),cs varchar(255),ct varchar(255),cu varchar(255),cv varchar(255),cw varchar(255),cx varchar(255),cy varchar(255),cz varchar(255),
ca1 varchar(255),cb2 varchar(255),cc3 varchar(255),cd4 varchar(255),ce5 varchar(255),cf6 varchar(255),cg7 varchar(255),ch8 varchar(255),ci9 varchar(255),cj10 varchar(255),ck11 varchar(255),cl12 varchar(255),cm13 varchar(255),
cn14 varchar(255),co15 varchar(255),cp16 varchar(255),cq17 varchar(255),cr18 varchar(255),cs19 varchar(255),ct20 varchar(255),cu21 varchar(255),cv22 varchar(255),cw23 varchar(255),cx24 varchar(255),cy25 varchar(255))
--Cargo data necesaria
INSERT INTO headeronly EXECUTE(@@sentencia)
--Genera sentencia
SELECT 'RESTORE LOG '+@base +' FROM '+@device+' WITH FILE= '+cf+' ,NORECOVERY' FROM headeronly
--Deja on-line la base
--SELECT 'RESTORE LOG '+@base +' FROM '+@device+' WITH FILE= '+max(cf)+' ,RECOVERY' FROM headeronly
Ej: sp_restorealog 'mibaseLOG_backup','mibase'
Abrazo virtual para todos y espero les sirva !!!
Hola como están ???, les comento que yo estoy con un cuadro gripal bastante molesto hace ya casí 10 días, espero se me pase algún día.
Hoy les voy a pasar algo que puede ser que les sirva y es un pequeño script para averiguar a que rol de base de datos pertenece cada usuario en la db.
El script es el siguiente:
use mibase
go
select C.name as RolName,A.groupuid as IdRol,B.name as Usuario
from sysmembers as A inner join sysusers as B
on A.memberuid = B.uid
inner join sysusers as C
on A.groupuid = C.uid
Nota: Sirve para las versiones 7.0, 2000 y 2005 de SQL Server.
Y como siempre, abrazo virtual para todos !!!.
Hola como están ? , bueno, hoy vamos a tratar como monitorear el espacio utilizado del log transaccional en MSSQL2K5. Bien sabemos que podemos monitorearlo desde la Consola Administrativa o SQL Server Management Studio, generando un reporte ya definido en forma standart, actualizándola con la función de la tecla F5, pero este método no resulta demasiado útil para seguir una transacción e ir chequeando cuando llega o supera un umbral determinado en un tiempo determinado, entonces para ello no nos queda otra que sumar una pequeñas líneas al código, las cuales son las siguientes:
--******************************************************************************
DECLARE @tran_log_espacio_usado table(
nombre_db sysname
, tamaño_log_mb float
, tamaño_log_usado_porcentaje float
, estado int
);
INSERT INTO @tran_log_espacio_usado
EXEC('DBCC SQLPERF ( LOGSPACE )') ;
SELECT nombre_db,tamaño_log_mb,tamaño_log_usado_porcentaje,getdate() as diahora FROM @tran_log_espacio_usado where nombre_db = 'mibase'
--******************************************************************************
Cabe aclarar que pueden generar un procedimiento almacenado o stored procedure que reciba parámetros y directamente llamarlo con el parámetro que represente el nombre de la base de datos.
Espero que sirva y les mando un abrazo virtual a todos !
JuanPL
Link's relacionados:
http://www.todosql.com/blog/200706/log-transaccional-en-sql-server-2005-...
http://www.todosql.com/blog/200705/mirror-y-log-transaccional-en-sql-ser...
Hoy les voy a comentar algo referido a la nueva versión de MS SQL Server o mejor dicho MSSQLServer2K5.
Escenario: Si corremos un script de generación de objetos en donde se esta utilizando ‘sp_tableoption’ con el parámetro 'insert row lock', para manejar lockeos nosotros mismos y no el dbms, podemos encontrar el siguiente error:
Msg 15600, Level 15, State 1, Procedure sp_tableoption, Line 48
An invalid parameter or option was specified for procedure 'sys.sp_tableoption'.
Msg 15600, Level 15, State 1, Procedure sp_tableoption, Line 48
An invalid parameter or option was specified for procedure 'sys.sp_tableoption'.
Solución: Debe comentariarse esta opcion, pues, no es soportada en SQL2K5 aunque en los book's figure que se acepta el parámetro, pero, solo de entrada, pues el motor ignora esta configuración.
Ej:
/****** Objeto: tabla [dbo].[MiTabla] fecha de la secuencia de comandos: 15/09/2000 16:00:00 ******/
CREATE TABLE [dbo].[Mitabla] (
[EventoID] [int] IDENTITY (1, 1) NOT NULL ,
[TID] [int] NOT NULL ,
[FechaHora] [datetime] NOT NULL ,
[Accion] [char] (2) NOT NULL ,
[Resultado] [char] (2) NOT NULL ,
[Co] [int] NOT NULL ,
[Origen] [varchar] (30) NULL ,
[Descripcion] [varchar] (500) NULL
) ON [PRIMARY]
GO
/****** Objeto: tabla [dbo].[Mitabla] Para que el lockeo se haga por registro ******/
--EXEC sp_tableoption 'Mi tabla', 'insert row lock', 'true'
GO
Espero que sirva y una abrazo virtual para todos.
JuanPL