NULLIF does not support set arguments error even though not a set - postgresql

the array_to_string is returning text (916-555-1212), however postgresql is treating it as set-operation even with explicit ::text casting.
select nullif(
array_to_string(
regexp_matches('9165551212', '(\d{3})?(\d{3})(\d{4})')::text[]
,'-')::text
, '');
ERROR: NULLIF does not support set arguments
yet I can use char_length which expects text and it works
select char_length(
array_to_string(
regexp_matches('9165551212', '(\d{3})?(\d{3})(\d{4})')::text[]
,'-')::text
)
char_length
-------------
12
yet wrap even that in a nullif and same error
select nullif(
char_length(
array_to_string(
regexp_matches('9165551212', '(\d{3})?(\d{3})(\d{4})')::text[]
,'-')::text
)
,12)
ERROR: NULLIF does not support set arguments

I had the same problem and it seems to be related to the regexp_matches function:
select nullif( (regexp_matches( '123', '(2)' ) )[1] , '' )
; -- ERROR: NULLIF does not support set arguments
select nullif( (regexp_matches( '123', '(2)' )::text[])[1]::text, '' )
; -- ERROR: NULLIF does not support set arguments
select nullif( ( select (regexp_matches( '123', '(2)' ) )[1] ), '' )
; -- ok: gives "2"
so just wrapping the result in a sub-select seems to solve it here as well :-/

Weird... It works if you do
select
nullif(
(
select array_to_string(
regexp_matches(
'9165551212',
'(\d{3})?(\d{3})(\d{4})'
)::text[]
, '-' )
)
, '')

Related

xmlserialize, xmlagg, xmltext used in the Postgres

I have a task is change the DB2 sql to Postgres sql. It has a problem in XML handle.
I tried to used this sql
SELECT xmlagg( ', <foo>abc</foo>') as YM
FROM TEST_Table"
It's working fine.
But
SELECT xmlagg( concat(', ', TRIM(CATEGORY))) as YM
from TEST_Table
is not working.
Error msg : SQL Error [42883]: ERROR: function xmlagg(text) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
My question is how to change the below DB2sql to Postgres sql ?
**SELECT substr( xmlserialize( xmlagg( xmltext( concat( ', ', TRIM(NM_TEXT) ) ) ) as varchar( 1024 ) ), 3, 128 ) as YM
FROM TEST_Table**

tSQLt AssertResultSetsHaveSameMetaData truncated response message in SQLTest

I'm trying to use tSQLt AssertResultSetsHaveSameMetaData to check the metadata from a query that returns a large number of columns.
When it fails the message that details the 'expected/but was' details is truncated, so I can't the two pieces of information to see what is wrong.
Is there a way to output the message so that it doesn't truncate (for example, to a file)?
It depends on what you are actually testing. I agree that on wide result sets the output from AssertResultsSetsHaveSameMetaData can be a little unwieldy. For stored procedures you would write your tests like this:
create procedure [ProcedureTests].[test SelectProcedure result set contract]
as
begin
create table #expected
(
name varchar(500) not null
, column_ordinal int not null identity(1,1)
, system_type_name varchar(500) not null
, Nullability varchar(16) not null
)
; with expectedCte (name, system_type_name, Nullability)
as
(
select 'ItemId' , 'int' , 'not null'
union all select 'ActorId' , 'int' , 'not null'
union all select 'LanId' , 'nvarchar(200)' , 'not null'
union all select 'ConsumerId' , 'int' , 'not null'
union all select 'ConsumerMoniker' , 'nvarchar(200)' , 'not null'
union all select 'ProfileTypeId' , 'int' , 'not null'
union all select 'ProfileTypeName' , 'varchar(50)' , 'not null'
union all select 'ProfileId' , 'int' , 'not null'
)
insert #expected
(
name
, system_type_name
, Nullability
)
select name, system_type_name, Nullability from expectedCte;
--! Act
select
name
, column_ordinal
, system_type_name
, case is_nullable when 1 then 'null' else 'not null' end as [Nullability]
into
#actual
from
sys.dm_exec_describe_first_result_set_for_object(object_id('mySchema.SelectProcedure'), 0);
--! Assert
exec tSQLt.AssertEqualsTable #expected, #actual;
end;
go
Whilst for views you could use this (slightly different) approach:
alter procedure [ViewTests].[test ViewName resultset contract]
as
begin
create table [ViewTests].[expected]
(
TransactionId int not null
, SourceId int not null
, SourceKey nvarchar(50) not null
, TransactionTypeId int not null
, TransactionStatusId int not null
, LastModified datetime not null
);
--! You comparison may be as simple as this (but see alternative approach below)
exec tSQLt.AssertEqualsTableSchema '[ViewTests].[expected]', 'mySchema.ViewName';
--!
--! Seems that is_nullable column on dm_exec_describe_first_result_set (used by tSQLt.AssertEqualsTableSchema)
--! can be a bit flakey where views are concerned so you may need to ignore nullability when testing
--! this view (so comment out that column in both SELECTs)
--!
select
c.name as [ColumnName]
, c.column_id as [ColumnPosition]
, case
when st.name in ('char', 'varchar', 'varbinary')
then st.name + '(' + case when c.max_length = -1 then 'max' else coalesce(cast(c.max_length as varchar(8)), '???') end + ')'
when st.name in ('nchar', 'nvarchar')
then st.name + '(' + case when c.max_length = -1 then 'max' else coalesce(cast(c.max_length / 2 as varchar(8)), '???') end + ')'
when st.name in ('decimal', 'numeric')
then st.name + '(' + coalesce(cast(c.precision as varchar(8)), '???') + ',' + coalesce(cast(c.scale as varchar(8)), '???') + ')'
when st.name in ('time', 'datetime2', 'datetimeoffset')
then st.name + '(' + coalesce(cast(c.precision as varchar(8)), '???') + ')'
else st.name
end as [DataType]
, c.[precision] as [NumericScale]
, c.scale as [NumericPrecision]
, c.collation_name as [CollationName]
, cast(case c.is_nullable when 1 then 'null' else 'not null' end as varchar(16)) as [Nullability]
into
#expected
from
sys.columns as c
inner join sys.types as st
on st.system_type_id = c.system_type_id
and st.user_type_id = c.user_type_id
where
c.[object_id] = object_id('[ViewTests].[expected]')
select
name as [ColumnName]
, column_ordinal as [ColumnPosition]
, system_type_name as [DataType]
, [precision ]as [NumericScale]
, scale as [NumericPrecision]
, collation_name as [CollationName]
, cast(case is_nullable when 1 then 'null' else 'not null' end as varchar(16)) as [Nullability]
into
#actual
from
sys.dm_exec_describe_first_result_set('select * from mySchema.ViewName, null, null)
exec tSQLt.AssertEqualsTable '#expected', '#actual' ;
end
go
In the even of any failures, the reason will be much clearer as the output is more like AssertEqualsTable.
You could try EXEC [tSQLt].[XmlResultFormatter]; before running your test. This is intended for use in "build server" scenarios, but could probably be pressed into service to show you more of the output in SSMS.

postgresql WITH statement doesn't find auxiliary statements

I have this query:
WITH words_not AS (
SELECT keywords.id
FROM keywords
WHERE keyword = any(array['writing'])
),actes_not AS (
SELECT actes_keywords.acte_id
FROM actes_keywords
WHERE actes_keywords.keyword_id IN (words_not)
)
SELECT actes.id,
actes.acte_date
FROM actes
WHERE actes.id <> all(actes_not);
This returns the following error:
ERROR: column "words_no" does not exist
LINE 1: ...ctes_keywords WHERE actes_keywords.keyword_id IN (mots_non))...
Each auxiliary statement in the WITH query is good (tested) and I thought I was staying pretty close to the manual: https://www.postgresql.org/docs/current/static/queries-with.html
I don't see why the auxiliary statement in the WITH query is not recognised.
You can't use a table reference in an IN (..) clause. You need a sub-query:
WITH words_not AS (
SELECT keywords.id
FROM keywords
WHERE keyword = any(array['writing'])
), actes_not AS (
SELECT actes_keywords.acte_id
FROM actes_keywords
WHERE actes_keywords.keyword_id IN (select id from words_not) --<< HERE
)
SELECT actes.id,
actes.acte_date
FROM actes
WHERE actes.id <> all(select id from actes_not); --<< HERE

SQL Server 2008 - split multi-value column into rows with unique values

In a SQL Server 2008 database, I have a column with multiple values separated by semi-colons. Some values contain colons. Sample data:
key:value;key2:value;blah;foo;bar;A sample value:whee;others
key:value;blah;bar;others
A sample value:whee
I want to get all the unique values from each row in separate rows:
key:value
key2:value
blah
foo
bar
A sample value:whee
others
I've looked at various split functions, but they all seem to deal with hard-coded strings, not strings coming from a column in a table. How can I do this?
Edit: Thomas' answer got it! Here was my final query:
With SampleInputs As
(
select distinct myColumn from [myDatabase].[dbo].myTable where myColumn != ''
)
, XmlCte As
(
Select Cast( '<z>' + Replace( myColumn, ';', '</z><z>' ) + '</z>' As xml ) As XmlValue
From SampleInputs As I
)
Select Distinct Y.z.value('.','nvarchar(max)') As Value
From XmlCte
Cross Apply XmlValue.nodes('//z') Y(z)
I'm guessing the XmlValue.nodes and Y.z.value stuff is magic. O_o
With a split function you use cross apply:
select distinct SS.part
from YourTable
cross apply dbo.SplitString(YourColumn, ';') as SS
Here the SplitString takes two arguments, the string column and the separator and has a column called part where the values are returned.
With SampleInputs As
(
Select 'key:value;key2:value;blah;foo;bar;A sample value:whee;others' As [Data]
Union All Select 'key:value;blah;bar;others'
Union All Select 'A sample value:whee'
)
, XmlCte As
(
Select Cast( '<z>' + Replace( I.[Data], ';', '</z><z>' ) + '</z>' As xml ) As XmlValue
From SampleInputs As I
)
Select Distinct Y.z.value('.','nvarchar(max)') As Value
From XmlCte
Cross Apply XmlValue.nodes('//z') Y(z)
Update
Here's a version of the above that handles entities:
With SampleInputs As
(
Select 'key:value;key2:value;blah;foo;bar;A sample value:whee;others' As [Data]
Union All Select 'key:value;blah;bar;others'
Union All Select 'A sample value:whee'
Union All Select 'A sample value:<Oops>'
)
, XmlGoo As
(
Select Cast(
Replace(
Replace( Cast( Z.XmlValue As nvarchar(max) ), '{{', '<z>' )
, '}}', '</z>')
As Xml ) As Xmlvalue
From (
Select Cast(
(
Select '{{' + Replace( [Data], ';', '}}{{' ) + '}}'
From SampleInputs
For Xml Path(''), type
) As Xml ) As XmlValue
) As Z
)
Select Distinct Z.data.value('.', 'nvarchar(max)')
From XmlGoo
Cross Apply XmlValue.nodes('/z') Z(data)

T-sql Common expression query as subquery

I have the following query:
WITH Orders(Id)
AS (
SELECT DISTINCT anfrageid FROM MPHotlineAnfrageAnhang
)
SELECT Id,
(
SELECT CONVERT(VARCHAR(255),anfragetext) + ' | '
FROM MPHotlineAnfrageAnhang
WHERE anfrageid = Id
ORDER BY anfrageid, erstelltam
FOR XML PATH('')
) AS Descriptions
FROM Orders
Its concatenates varchar values of diferents rows grouped by an id. But now i want to include it as a subquery and it gives some errors i cant solve.
Simplified example of use:
select descriptions from
(
WITH Orders(Id)
AS (
SELECT DISTINCT anfrageid FROM MPHotlineAnfrageAnhang
)
SELECT Id,
(
SELECT CONVERT(VARCHAR(255),anfragetext) + ' | '
FROM MPHotlineAnfrageAnhang
WHERE anfrageid = Id
ORDER BY anfrageid, erstelltam
FOR XML PATH('')
) AS Descriptions
FROM Orders
) as tx where id=100012
Errors (Aproximate translation from spanish):
-Incorrect sintaxis near 'WITH'.
-Incorrect sintaxis near 'WITH'. If the instruction is a common table expression or a xmlnamespaces clause, the previous instruction must end with semicolon.
-Incorrect sintaxis near ')'.
What im doing wrong?
Chain your queries as CTEs, like this:
WITH Orders(Id) AS (
SELECT DISTINCT anfrageid
FROM MPHotlineAnfrageAnhang
),
OrderDescs AS (
SELECT Id, (
SELECT CONVERT(VARCHAR(255),anfragetext) + ' | '
FROM MPHotlineAnfrageAnhang
WHERE anfrageid = Id
ORDER BY anfrageid, erstelltam
FOR XML PATH('')
) AS Description
FROM Orders
)
SELECT Description
FROM OrderDescs
WHERE Id = 100012
You can have as many CTEs as you like, each referencing the previous, before the actual query.
Also, you need to have a semi-colon before a WITH statement.
;with Orders(id)
Or terminate the previous statement with the semi-colon instead.