Category Archives: sqlserver

fecha a texto sql server / date to text sql server / 文字日期


Normalmente las bases de datos SQL Server están normalizadas para que cuando hacemos un select sobre un campo fecha nos retorne en el formato local que necesitamos, año/mes/día – mes/día/año – año-mes-día, etc. pero si necesitamos un formato específico y además en formato texto esta es una forma fácil de hacerlo:

FormatSQL QueryExample
1select convert(varchar, getdate(), 1)12/31/19
2select convert(varchar, getdate(), 2)19.12.31
3select convert(varchar,getdate(),3)31/12/19
4select convert(varchar,getdate(),4)31.12.19
5select convert(varchar,getdate(),5)31-12-19
6select convert(varchar,getdate(),6)31 Dec 19
7select convert(varchar,getdate(),7)Dec 31, 19
10select convert(varchar,getdate(),10)12-31-19
11select convert(varchar,getdate(),11)19/12/31
12select convert(varchar,getdate(),12)191231
23select convert(varchar,getdate(),23)2019-12-31
101select convert(varchar,getdate(),101)12/31/2019
102select convert(varchar,getdate(),102)2019.12.31
103select convert(varchar,getdate(),103)31/12/2019
104select convert(varchar,getdate(),104)31.12.2019
105select convert(varchar,getdate(),105)31-12-2019
106select convert(varchar,getdate(),106)31 Dec 2019
107select convert(varchar,getdate(),107)Dec 31, 2019
110select convert(varchar,getdate(),110)12-31-2019
111select convert(varchar,getdate(),111)2019/12/31
112select convert(varchar,getdate(),112)20191231
Date to text format

El que hace el truco es el convert y la clave el tercer parámetro, según este se devuelve uno u otro string.

The one that does the trick is the convert and the key is the third parameter, according to which one or the other string is returned.

Column exists in SQL Server database / Existe columna en Base de Datos SQL Server / 列が存在します


The easy way to find if a column exists in any database is using the function COL_LENGTH(‘database’, ‘column_name’) if this returns NULL is because the column does not exist. / La forma más fácil de saber si existe una columna en cualquier base de datos es usando la función COL_LENGTH(‘basedatos’, ‘nombre_columna’) si retorna NULL es porque la columna no existe. / データベースに列が存在するかどうかを簡単に確認するには、列が存在しないため、これがNULLを返す場合、COL_LENGTH( ‘database’、 ‘column_name’)関数を使用します。

Example:
create database dbtest1
GO
use dbtest1
GO
create table ttest(id int identity primary key, name varchar(40))
GO
create database dbtest2
GO
use dbtest2
GO
create table ttest(id int identity primary key, name varchar(40), lastname varchar(50))
GO


select COL_LENGTH('[dbtest2].dbo.ttest', 'lastname')

returns 50

select COL_LENGTH('[dbtest1].dbo.ttest', 'lastname')

returns NULL

We are still using dbtest2 but We can check from this database other databases, and the result is that this column does not exists in database dbtest1 table ttest. / Continuamos usando dbtest2 pero podemos chequear desde esta base de datos otras bases de datos y el resultado es que la columna no existe en la tabla ttest base de datos dbtest1.

select COL_LENGTH('[dbtest1].dbo.ttest', 'name')

returns 40

The column exists in database dbtest1 table ttest. / la columna si existe en la tabla ttest base de datos dbtest1

Como monitorear ejecución de triggers en SQL SERVER Profiler / monitor trigger execution


Normalmente por defecto el Sql Server profiler no muestra los resultados en las ejecuciones de triggers, por eso debemos activar esta función, ir a “Events Selection”, Click en “Show all events”, luego buscar “Stored Procedures” y allí marcar los eventos: “SP:StmtCompleted” y “SP:StmtStarting”

monitor trigger

Lista de eventos a seleccionar para monitorear triggers

Ahora ya se pueden visualizar los resultados de ejecución de triggers:

trigger monitor result
En este momento en la ventana de resultados se ve la ejecución del trigger

Normally by default Sql Server profiler is not showing triggers execution, we must activate the option, so, go to “Events Selection”, Click “Show all events”, search “Stored Procedures” select events: “SP:StmtCompleted” y “SP:StmtStarting”

After this you can now watch the trigger execution.

Hacer Ciclos o iteraciones en SQL Server / How to make cycles or iterate in SQL Server


Iteración-2

Algunas veces necesitamos en un store procedure recorrer un conjunto de resultados, vamos a usar tablas temporales para este ejemplo. / Sometimes we need to iterate over a resultset, let’s use some temporary tables in this example:

create table #tmpartic(codigo varchar(10), nombre varchar(50), price int)
insert into #tmpartic values('001', 'KEYBOARD / TECLADO', 70)
insert into #tmpartic values('002', 'MOUSE / RATON', 90)
insert into #tmpartic values('003', 'PEN / LAPICERO', 45)
insert into #tmpartic values('004', 'DISPLAY / MONITOR', 150)
insert into #tmpartic values('005', 'HARD DISK / DISCO DURO', 200)

create table #tmpcli(client varchar(10), City varchar(30), limit int)
insert into #tmpartic values('5551010', 'Bogota', 100)
insert into #tmpartic values('5156225', 'Bangladesh', 300)
insert into #tmpartic values('6859852', 'Pekin', 500)
insert into #tmpartic values('7851215', 'Tokio', 500)
insert into #tmpartic values('8989822', 'Sidney', 350)

create table #tmpped(client varchar(10), article varchar(10), price int)

Ahora necesitamos crear registros en la tabla tmpcli para cada cliente todos los artículos mientras no se pase de su límite. /

Now we need to create records in tmpcli table for each client every article without being over limit.

Para esto creamos 2 tablas temporales #tmpartic con cada artículo y su precio y #tmpcli con cada cliente y su límite. El ciclo principal es sobre la tabla temporal de clientes entonces obtenemos su límite y mientras tenga límite disponible agregamos un registro en la tabla #tmpped, por cada registro agregado vamos disminuyendo el precio del artículo para que no se vaya a pasar. El ciclo while se controla mediante la columna kctrl que empieza en null y tras cada iteración cambia a 1 así ya no se procesa más. Para los artículos se debe volver a actualizar en null cuando se cambia de cliente para garantizar que se procesan de nuevo todos los artículos para cada cliente. /

For this we create 2 temporary tables #tmpartic with each article and price y #tmpcli for each client and limit. Main cycle runs on clients temporary table, we read his limit and while limit is available we add a new record in #tmpped, for each record added we subtract the price of the article preventing to add more than expected. The cycle is controled with the column kctrl that starts in null and after every iteration it changes to 1 that way is no longer used. For the articles this column must be updated to null when client is changed to warranty all the articles are processed for each client.

DECLARE @nLIMIT int, @nRECNUM int, @cCLI varchar(10);
DECLARE @nRECNP int, @cART varchar(10), @nPRIC int;
SELECT null kctrl, codigo, price, ROW_NUMBER() OVER(ORDER BY codigo) as recnum into #selpro FROM #tmpartic;
SELECT null kctrl, client, limit, ROW_NUMBER() OVER(ORDER BY limit) as recnum into #selcli FROM #tmpcli;
WHILE (SELECT count(*) FROM #selcli WHERE isnull(kctrl, 0) = 0) > 0
BEGIN
  SET @nRECNUM=(SELECT MIN(recnum) FROM #selcli WHERE ISNULL(kctrl, 0) = 0)
  SELECT @nLIMIT=limit, @cCLI=client FROM #selcli WHERE recnum=@nRECNUM
  UPDATE #selpro SET kctrl=null
  WHILE (SELECT count(*) FROM #selpro WHERE isnull(kctrl, 0) = 0) > 0
    BEGIN
      SET @nRECNP=(SELECT MIN(recnum) FROM #selpro WHERE ISNULL(kctrl, 0) = 0)
      SELECT @cART=codigo, @nPRIC=price FROM #selpro WHERE recnum=@nRECNP
      IF @nLIMIT>=@nPRIC
        BEGIN
          INSERT INTO #tmpped(client, article, price) VALUES(@cCLI, @cART,@nPRIC)
          SET @nLIMIT=@nLIMIT-@nPRIC
        END
      ELSE BREAK
      UPDATE #selpro SET kctrl=1 WHERE recnum=@nRECNP
  END
  UPDATE #selcli SET kctrl=1 WHERE recnum=@nRECNUM
END

Ahora vamos a validar / let’s now validate:
SELECT * from #selcli

clientes

SELECT * from #selpro
articles

SELECT * from #tmpped
peds

Verificación de resultados / Verification of results

Client $Limit $Total Peds ok?
5551010 100 70 Yes
5156225 300 205 Yes
8989822 350 205 Yes
6859852 500 355 Yes
7851215 500 355 Yes

Ahora usted podría cambiar los límites en los clientes y reiniciar el proceso para validar contra diferentes valores /

Now you can change the limits in client and restart the process to verify against different values.

Para borrar todas las tablas / to delete all the tables:

DROP TABLE #tmpartic
DROP TABLE #tmpcli
DROP TABLE #tmpped
DROP TABLE #selpro
DROP TABLE #selcli

Preguntas? / Questions?

Seleccionar registros de una tabla y todos sus registros relacionados. / Select records from a table and all related records.


Este es el comportamiento por defecto de un select sobre múltiples tablas relacionadas, nos devuelve un resultado completo incluyendo los registros de la tabla principal más todos los relacionados / This is the default behavior when performing queries against multiple related tables.

create table #tmpartic(codigo varchar(10), nombre varchar(50))
insert into #tmpartic values('001', 'KEYBOARD / TECLADO')
insert into #tmpartic values('002', 'MOUSE / RATON')
insert into #tmpartic values('003', 'PEN / LAPICERO')
insert into #tmpartic values('004', 'DISPLAY / MONITOR')
insert into #tmpartic values('005', 'HARD DISK / DISCO DURO')

create table #tmpbars(article varchar(10), codbar varchar(20))
insert into #tmpbars values('001', '8909001212')
insert into #tmpbars values('001', '8909001213')
insert into #tmpbars values('001', '8909001214')
insert into #tmpbars values('003', '8909051223')
insert into #tmpbars values('004', '8909061245')
insert into #tmpbars values('005', '8909071241')
insert into #tmpbars values('005', '8909071242')

create table #tmpprov(article varchar(10), proveed varchar(10))
insert into #tmpprov values('001', '101010')
insert into #tmpprov values('001', '102010')
insert into #tmpprov values('001', '103010')
insert into #tmpprov values('002', '102010')
insert into #tmpprov values('003', '103010')
insert into #tmpprov values('004', '101010')
insert into #tmpprov values('004', '102010')
insert into #tmpprov values('004', '104020')
insert into #tmpprov values('005', '104030')

Ahora vamos a seleccionar con un left normal / select with a normal “left” query :

select art.codigo, art.nombre, isnull(bar.codbar,'') as codbar, isnull(pro.proveed,'') as proveed
from #tmpartic art
left join #tmpbars bar on art.codigo=bar.article
left join #tmpprov pro on art.codigo=pro.article

Esto nos retorna todos los registros repetidos artículos en barras y en proveed, se puede ver el artículo 001 que se repite 9 veces / this is returning 9 repeated records of the article 001:

todoslosregistros
Record with all related records

Otra forma de conseguir el mismo resultado:

select art.codigo, art.nombre, isnull(bar.codbar,'') as codbar, isnull(pro.proveed,'') as proveed
from #tmpartic art
outer apply (select * from #tmpbars where art.codigo=article ) bar
outer apply (select * from #tmpprov where art.codigo=article ) pro

Y finalmente, esto para motivos solo de verificación de velocidad o solo por diversión, un select que devuelve una combinación completa de todos los registros. /And finally just to check execution performance or just for fun, a query that returns a complete combination of all records:


select art.codigo, art.nombre, bar.codbar, pro.proveed
from #tmpartic art, #tmpbars bar, #tmpprov pro

exponentialrecords
Exponential

seleccionar registro de una tabla y 1 solo registro relacionado / select records from a table and only 1 related record.


Por ejemplo que tenemos una tabla de artículos y una tabla de códigos de barra relacionados con dicho artículo y necesitamos por cada artículo 1 solo código de barra porque con esto sabremos si tiene barra o no y no requerimos todos los códigos de barra.  / For example we have an articles table and barcodes table, we need for each article show just 1 barcode that will show that the article has barcode no matter how many.

Estas serían las tablas / example tables:


create table #tmpartic(codigo varchar(10), nombre varchar(50))
insert into #tmpartic values('001', 'KEYBOARD / TECLADO')
insert into #tmpartic values('002', 'MOUSE / RATON')
insert into #tmpartic values('003', 'PEN / LAPICERO')
insert into #tmpartic values('004', 'DISPLAY / MONITOR')
insert into #tmpartic values('005', 'HARD DISK / DISCO DURO')


create table #tmpbars(article varchar(10), codbar varchar(20))
insert into #tmpbars values('001', '8909001212')
insert into #tmpbars values('001', '8909001213')
insert into #tmpbars values('001', '8909001214')
insert into #tmpbars values('003', '8909051223')
insert into #tmpbars values('004', '8909061245')
insert into #tmpbars values('005', '8909071241')

Ahora vamos a seleccionar con un left normal / select with a normal “left” query :

select art.codigo, art.nombre, isnull(bar.codbar,'') as codbar from #tmpartic art left join #tmpbars bar on art.codigo=bar.article

Esto nos retorna todos los registros repetidos artículos en barras, se puede ver el artículo 001 que se repite 3 veces / this is returning 3 repeated records of the article 001:

repetidos

Ahora veamos la magia, vamos a usar la instrucción que nos retornará solo 1 registro relacionado / Now let’s watch the magic, with this instruction we will have only 1 related record:

select art.codigo, art.nombre, isnull(bar.codbar,'') as codbar from #tmpartic art outer apply(select top 1 article, codbar from #tmpbars where article=art.codigo) bar

Resultado, no se repiten los registros de barras y sale solo 1 barra / This is the result, just 1 barcode for each article:

repetidos_no

Podemos usar este sql cuando necesitamos filtrar repetidos desde la misma ejecución de la sentencia SQL. / We can use this sql when we need to filter repeated records since the start of the Sql sentence.

 

 

Filas a Columnas SQL Server / Rows to Cols in SQL Server


Tenemos una consulta de 4 columnas y las 2 primeras las necesitamos tal como se ven pero de las 2 siguientes la 3ra la necesitamos como columnas según el contenido que tenga y la cuarta como los datos que van en dicha nueva columna. De tal forma que si en la 3ra columna hay 3 o 5 diferentes datos, se crearán 3 o 5 nuevas columnas. A continuación unos datos de ejemplo para entender bien el proceso. / We have 4 Cols and the first 2 we need them exactly as they are, but the next 2 this way, the third must be new colum as different value it has, the fourth is the data for the columns created by the third one. Now this is an example to understand better this process:


create table #tmpartic(codigo varchar(10), nombre varchar(50))
create table #tmpartic_idi(artic varchar(10), idioma varchar(3), traducc varchar(50))
create table #tmpidioma(codigo varchar(3), nombre varchar(50))


insert into #tmpidioma values('ENG', 'ENGLISH')
insert into #tmpidioma values('CAT', 'CATALÀ')
insert into #tmpidioma values('FRE', 'FRENCH')


insert into #tmpartic values('001', 'HELADO DE VAINILLA')
insert into #tmpartic values('002', 'HELADO DE CHOCOLATE')
insert into #tmpartic values('003', 'MALTEADA DE FRESA')
insert into #tmpartic values('004', 'TORTA DE QUESO')
insert into #tmpartic values('005', 'CREMA BATIDA')


insert into #tmpartic_idi values('001','ENG', 'VANILLA ICE CREAM')
insert into #tmpartic_idi values('001','CAT', 'GELAT DE VAINILLA')
insert into #tmpartic_idi values('001','FRE', 'GLACE À LA VANILLE')
insert into #tmpartic_idi values('002','ENG', 'CHOCOLATE ICE CREAM')
insert into #tmpartic_idi values('002','CAT', 'GELAT DE XOCOLATA')
insert into #tmpartic_idi values('002','FRE', 'GLACE AU CHOCOLAT')
insert into #tmpartic_idi values('003','ENG', 'STRAWBERRY SHAKE')
insert into #tmpartic_idi values('003','CAT', 'MALTAT DE MADUIXA')
insert into #tmpartic_idi values('003','FRE', 'FRAISE MALTE')
insert into #tmpartic_idi values('004','ENG', 'CHEESECAKE')
insert into #tmpartic_idi values('004','CAT', 'COCA DE FORMATGE')
insert into #tmpartic_idi values('004','FRE', 'GÂTEAU AU FROMAGE')
insert into #tmpartic_idi values('005','ENG', 'WHIPPED CREAM')
insert into #tmpartic_idi values('005','CAT', 'CREMA BATUDA')
insert into #tmpartic_idi values('005','FRE', 'CRÈME FOUETTÉE')

--esta es la consulta normal que nos muestra las traducciones por cada artículo un dato interesante "article" es la misma palabra para catalán, inglés y francés.
--this is the normal query to bring all the translations for each article by the way "article" is the same word in the 3 languages
select A.CODIGO, A.NOMBRE, C.NOMBRE as IDIOMA, B.TRADUCC
from #tmpartic A
join #tmpartic_idi B on A.CODIGO=B.ARTIC
join #tmpidioma C on B.IDIOMA=C.CODIGO

Esta consulta muestra todos los artículos con cada traducción en estilo filas. / This query is showing all the articles with each traduction in row style:

Resultado Normal
Normal resultset, we want to change the IDIOMA data to cols

--ahora, aquí está la magia, nosotros le decimos al sql server que le proporcionaremos los nombres de columnas en la variable @cols
--now, here is the magic, we are telling sql server that we will provide the column names in the @cols variable
--then we will query the data with the dynamic result for the columns.
declare @cols as nvarchar(4000), @query as nvarchar(4000)
select @cols=STUFF((select ',' + quotename(RTRIM(NOMBRE))
from #tmpidioma group by nombre for xml path(''),type).value('.', 'varchar(4000)'),1,1,'')
--print @cols
set @query= N'select codigo,nombre,'+@cols+ N' from (
select A.CODIGO, A.NOMBRE, C.NOMBRE as IDIOMA, B.TRADUCC
from #tmpartic A
join #tmpartic_idi B on A.CODIGO=B.ARTIC
join #tmpidioma C on B.IDIOMA=C.CODIGO
where 1=1
) P PIVOT(
max(traducc) for idioma in ('+@cols+N')
) as pivot_table '
--print @query
exec sp_executesql @query

Y este es el resultado final. / This is the final result:

Resultado Esperado
Resultset rows to cols

Todo se puede hacer en un script sql, pero también se puede crear un stored procedure. Depende de para que necesite utilizar este proceso. / You can do this in a script sql file, but also you can create a stored procedure. It depends on the requirement that you are working on.

Listar todos los stored procedures en SQL SERVER


Para cuando necesitamos saber que tantos SPs hay en un servidor de SQL Server / If you need to find all the SPs in a SQL Server:

create table #temptable(bd varchar(50) null, name varchar(150) null, object_id integer null, modify_date datetime null)

use master
execute sp_MSforeachdb ‘use [?];insert into #temptable select ”?”,name, object_id, modify_date from sys.procedures’

select * from #temptable

Tenga en cuenta que esto puede durar varios minutos dependiendo del tamaño del SQL Server. / Note that running time of this maybe take several minutes depending on the SQL Server Size.

Error en la llamada a procedimiento remoto. [0x800706be]


Este error me salió luego de instalar el SQL SERVER 2014 sobre una máquina donde ya tenía previamente SQL SERVER 2008R2, al abrir el Sql Server Configuration Manager sale este error:

error-sql-server-2014-configuration-manager

El problema es que se está abriendo el configurador del viejo 2008, se debe abrir el configurador para SQL SERVER 2014, de otra forma seguirán viendo el error.

Al abrir el Sql Server Configuration Manager del 2014 ya aparecerán bien todas las instancias:

sql-server-configuration-manager-2014