About iBatis mapped parameters - ibatis

when i have a query for ibatis like this
<insert id="createSomething" parameterClass="com.abc.something.CreateSomething">
INSERT INTO ABC (
MASTER_ID
)
VALUES (
#masterId:NUMERIC:-1#
)
</insert>
with pojo CreateSomething having int masterId = -1 with getter and setter.
what is the meaning of #masterId:NUMERIC:-1#, here i can understand masterId is of NUMERIC type but what is the associated -1 use here, and what will be the equivalent Mybatis query be.

Related

Is it possible to perform a regex pattern match in a SQL Server varchar(max) column and return the match?

I have a log table that has some records that have this type of pattern:
.... "RefundId":"re_1ABasdf234234343434", "..."....
I want to extract and return the value of the RefundId in a column in a select statement, is this possible?
If there is only one Refund_ID for each row then you can use something like this:
--Create table
create table T1 (
T1_id int identity(1,1) primary key clustered,
Log_Data varchar(max) null
)
--Insert test data
insert T1(Log_Data)
values('.... "RefundId":"re_1ABasdf234234343434", "..."....'),
(' "RefundId":"JHHJJHJHJHJJHJH", "..."....'),
(''),
(null)
--Get some results
select *, left(substring(Log_Data, patindex('%"RefundId":"%', Log_Data)+12, 20000000), patindex('%"%', substring(Log_Data, patindex('%"RefundId":"%', Log_Data)+12, 20000000)) + case when patindex('%"%', substring(Log_Data, patindex('%"RefundId":"%', Log_Data)+12, 20000000)) > 0 then -1 else 0 end ) Refund_ID
from T1
If there are multiple Refund_IDs for each value then you will have to find a different method.
You can use the keyword LIKE
SELECT RefundId
FROM MyTable
WHERE RefundId LIKE 'some pattern'

Conversion failed when converting the vardhar value 'abc' to data type int

I am inserting data from one table to another so when inserting I got above error mentioned in title
Insert into dbo.source(
title
)
Select
Title from dbi.destination
title in dbo.source table is of INT data type and title in dbo.destination table is of Varchar data type and I have data like abc, efg, etc. in the dbo.destination table.
So how to solve this now or is it possible to convert and insert values?
You can use SQL Server try_cast() function as shown below. Here is the official documentation of TRY_CAST (Transact-SQL).
It Returns a value cast to the specified data type if the cast succeeds; otherwise, returns null.
Syntax
TRY_CAST ( expression AS data_type [ ( length ) ] )
And the implementation in your query.
INSERT INTO dbo.source (title)
SELECT try_cast(Title AS INT)
FROM dbi.destination
Using this solution you need to be sure you have set the column allow null true otherwise it will give error.
If you do not want to set the allow null then you need minor changes in select query as shown below - passing the addition criteria to avoid null values.
Select ... from ... where try_cast(Title AS INT) is not null
You must use isnumeric method of SQL for checking is data numeric or not
CONVERT(INT,
CASE
WHEN IsNumeric(CONVERT(VARCHAR(12), a.value)) = 1 THEN CONVERT(VARCHAR(12),a.value)
ELSE 0 END)
Think about your data types - obviously you cannot have a text string like 'abc' in a column that is defined to hold integers.
It makes no sense to copy a string value into an integer column, so you have to confirm how you want to handle these - do you simply discard them (what is the impact of throwing data away?) or do you replace them with some other value?
If you want to ignore them and use NULL in place then use:
INSERT dbo.Source (Title)
SELECT CASE
WHEN ISNUMERIC(Title) = 1 THEN CAST(Title as INT)
ELSE NULL
END
FROM dbo.Destination
If you want to replace the value then simply change NULL above to the value you want e.g. 0
You can use regex to root out non numeric characters
Insert into dbo.source(
title
)
Select
case when Title not like '%[^0-9]%' then null else cast(Title as int) end as Title
from dbi.destination
Just filter only numeric field from destination table like as below:
Insert into dbo.source(
title
)
Select
Title from dbi.destination
where ISNUMERIC(Title) = 1

Suggestions: xQuery where filter predicate delivers unexpected results

I have the following xml which is being parsed via a MSSQL database using OPENXML with an xquery filter to grab the right rows. Unfortunately, it doesn't seem to grab the appropriate rows, which has me scratching my head.
Using the following XML, I only want to insert the single email address where the Method="Insert", and ignore the remaining two addresses where Method is not present or has another value (which were previously inserted).
<Entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ActiveEntityID="0">
<Entity_Businesses>
<Entity_Business EntityTypeID="5" EntityRoleTypeID="9" Method="Update" Name="test business 76" EIN="" EmployeeCount="75" TotalAssets="750000.00">
<Entity_Emails>
<Entity_Email ID="85" EmailAddress="jones#company.com" />
<Entity_Email ID="0" EmailAddress="smith#company.com" Method="Insert"/>
</Entity_Emails>
<Entity_Contacts>
<Entity_Contact ID="162" EntityTypeID="4" EntityRoleTypeID="9" FName="Joe" MName="k" LName="Smith" SSN="444-44-444" JobTitleID="0" DOB="2007-02-27T00:00:00">
<Entity_Emails>
<Entity_Email ID="86" EmailAddress="individual#test.com"/>
</Entity_Emails>
</Entity_Contact>
</Entity_Contacts>
<Entity_Business>
</Entity_Businesses>
</Entities>
I am using this sql statement:
INSERT into Entity_Email(bsCol, EmailAddress, xmlID, xmlPID)
SELECT DENSE_RANK() OVER( ORDER BY y.parentid ) AS elementid, z.EmailAddress, y.parentid, z.ID
FROM OPENXML( #hDoc, '//Entity_Emails', 1 )
WITH (parentid int '#mp:parentid', id int '#mp:id' ) y
INNER JOIN OPENXML(#hDoc, N'//Entity_Emails/Entity_Email',1) WITH (EmailAddress nvarchar(100), xmlID int '#mp:id', parentid int '#mp:parentid') as z
ON y.id = z.parentid
WHERE #pRI.value('(//Entity_Emails/Entity_Email/#Method)[1]','nvarchar(50)') = 'Insert';
As-is, all three email addresses will be inserted, even though the first and last email node do not have a 'Method" attribute. However if I add 'Method = "DontAdd"' to the other two email addresses, nothing gets inserted.
I have also tried using the predicate:
WHERE #pRI.exist('//Entity_Emails/Entity_Email[#Method="Insert"]') =1;
The result is similar - it inserts all rows, and seems to ignore the fact that two of the Email_Address elements do not have an attribute Method="Insert", regardless of whether the Method attribute exists.
The goal is to filter the xml as it is shredded and only add the email address with the attribute Method="Insert". Right now what I believe I have is actually "If you find Method = 'Insert' in the dataset, insert all rows" vs. "if you find method = 'insert', insert only those rows which have that attribute."
Thank you in advance.
Please note the following answer for those that might be helped in the future. After retrieving the column 'Method' in the z aliased query, I was able to use standard t-sql to filter the results correctly and then insert the correct rows.
INSERT into Entity_Email(bsCol, EmailAddress, xmlID, xmlPID)
SELECT DENSE_RANK() OVER( ORDER BY y.parentid ) AS elementid, z.EmailAddress, z.xmlID, y.parentid
FROM OPENXML( #hDoc, '//Entity_Emails', 1 )
WITH (parentid int '#mp:parentid', id int '#mp:id' ) y
INNER JOIN OPENXML(#hDoc, N'//Entity_Emails/Entity_Email',1) WITH (EmailAddress nvarchar(100), xmlID int '#mp:id', parentid int '#mp:parentid', Method nvarchar(50) '#Method') as z
ON y.id = z.parentid
WHERE z.Method = 'Insert'

Is there a way to add a logical Operator in a WHERE clause using CASE statements? - T-SQL

I searched the web but cannot find a solution for my problem (but perhaps I am using the wrong keywords ;) ).
I've got a Stored Procedure which does some automatic validation (every night) for a bunch of records. However, sometimes a user wants to do the same validation for a single record manually. I thought about calling the Stored Procedure with a parameter, when set the original SELECT statement (which loops through all the records) should get an AND operator with the specified record ID. I want to do it this way so that I don't have to copy the entire select statement and modify it just for the manual part.
The original statement is as follows:
DECLARE GenerateFacturen CURSOR LOCAL FOR
SELECT TOP 100 PERCENT becode, dtreknr, franchisebecode, franchisenemer, fakgroep, vonummer, vovolgnr, count(*) as nrVerOrd,
FaktuurEindeMaand, FaktuurEindeWeek
FROM (
SELECT becode, vonummer, vovolgnr, FaktuurEindeMaand, FaktuurEindeWeek, uitgestfaktuurdat, levdat, voomschrijving, vonetto,
faktureerperorder, dtreknr, franchisebecode, franchisenemer, fakgroep, levscandat
FROM vwOpenVerOrd WHERE becode=#BecondeIN AND levdat IS NOT NULL AND fakstatus = 0
AND isAllFaktuurStukPrijsChecked = 1 AND IsAllFaktuurVrChecked = 1
AND (uitgestfaktuurdat IS NULL OR uitgestfaktuurdat<=#FactuurDate)
) sub
WHERE faktureerperorder = 1
GROUP BY becode, dtreknr, franchisebecode, franchisenemer, fakgroep, vonummer, vovolgnr,
FaktuurEindeMaand, FaktuurEindeWeek
ORDER BY MIN(levscandat)
At the WHERE faktureerperorder = 1 I came up with something like this:
WHERE faktureerperorder = 1 AND CASE WHEN #myParameterManual = 1 THEN vonummer=#vonummer ELSE 1=1 END
But this doesn't work. The #myParameterManual indicates whether or not it should select only a specific record. The vonummer=#vonummer is the record's ID. I thought by setting 1=1 I would get all the records.
Any ideas how to achieve my goal (perhaps more efficient ideas or better ideas)?
I'm finding it difficult to read your query, but this is hopefully a simple example of what you're trying to achieve.
I've used a WHERE clause with an OR operator to give you 2 options on the filter. Using the same query you will get different outputs depending on the filter value:
CREATE TABLE #test ( id INT, val INT );
INSERT INTO #test
( id, val )
VALUES ( 1, 10 ),
( 2, 20 ),
( 3, 30 );
DECLARE #filter INT;
-- null filter returns all rows
SET #filter = NULL;
SELECT *
FROM #test
WHERE ( #filter IS NULL
AND id < 5
)
OR ( #filter IS NOT NULL
AND id = #filter
);
-- filter a specific record
SET #filter = 2;
SELECT *
FROM #test
WHERE ( #filter IS NULL
AND id < 5
)
OR ( #filter IS NOT NULL
AND id = #filter
);
DROP TABLE #test;
First query returns all:
id val
1 10
2 20
3 30
Second query returns a single row:
id val
2 20

Can I have a custom enumeration data-type in Sql Server?

In my sql code i'm passing around a bunch of magic numbers :-
AnimalType TINYINT
/*
AnimalType can be one of the following :-
1. Cat
2. Dog
3. Bird
....
*/
Is there anyway i could make this a custom type / enumeration.
eg.
AnimalType ANIMAL
and it's constrained to contain a number between 1 <-> whatever (eg. 3 in my example above).
or constrained to strings. eg. AnimalType = 'Cat' .. etc ?
Cheers!
Edit
I know what LookUp tables are. This is not for a lookup table, but for some data passed to a number of stored procedures. Instead of passing in Magic Numbers, I wish to pass in an enumeration OR at least some contrained number (eg. numbers 1<->5), etc...
There are no enumeration types. However, you can create user defined functions to translate back and forth between INTs that you map to enumerated values.
To generate friendly names for an AnimalType based of 'INT' you could do something like this:
UDF to generate friendly names:
CREATE FUNCTION ihAnimalTypeDesc
(
#AnimalType INT
)
RETURNS VARCHAR(20)
AS
BEGIN
IF #AnimalType IS NULL
RETURN NULL
DECLARE #Temp AS VARCHAR(20)
SET #Temp = CASE #AnimalType
WHEN 1 THEN 'Cat'
WHEN 2 THEN 'Dog'
WHEN 3 THEN 'Snake'
END
RETURN #Temp
END
A SELECT statement could uses the UDF like so:
SELECT A.AnimalName, dbo.ihAnimalTypeDesc(A.AnimalType)
FROM Animals A
Here is a UDF to return true or false if an animal is of a particular type:
CREATE FUNCTION IsCat
(
#AnimalType INT
)
RETURNS BIT
AS
BEGIN
IF #AnimalType IS NULL
RETURN NULL
IF #AnimalType = 1
RETURN 1
RETURN 0
END
Here is an example using the above UDF. NOTE: you have to be careful with performance issue when doing this in the WHERE clause.:
SELECT AnimalName
FROM Animals
WHERE dbo.IsCat(AnimalType)
Enumeration is like a FOREIGN KEY to a table, but without a table.
Create a table and make a FOREIGN KEY constraint:
CREATE TABLE AnimalType (id INT NOT NULL PRIMARY KEY, name VARCHAR(50) NOT NULL)
CREATE TABLE Animal (
id INT NOT NULL PRIMARY KEY,
type INT NOT NULL,
name VARCHAR(50) NOT NULL,
CONSTRAINT FK_animal_type FOREIGN KEY (type) REFERENCES AnimalType(id)
)
You can try to add something like this:
CREATE VIEW AnimalType AS
SELECT
10 AS Cat
,20 AS Dog
,30 AS Bird
to use it:
DECLARE #animal INT
SELECT #animal = Bird FROM AnimalType
as per your latest edit, about needing to pass in parameters. T-SQL has the basics to to simple stuff in addition to the heavy lifting SQL. There are no enumeration data-types. If that is what you want, you can handle it in the following way:
create procedure YourProcedure
( #param1 int
,#param2 varchar(5)
,#param3 varchar(5)
)
as
DECLARE #Value3 int
IF #param1 IS NULL OR #param1<1 OR #param1>5
BEGIN
return 1 --error out of range param
END
IF NOT EXISTS (SELECT Value FROM LookUpTable WHERE Value=#param2)
BEGIN
return 2 --error out of range param
END
SELECT #Value3=IntValue FROM OtherLookupTable WHERE StrValue=#param3
IF #Value3 IS NULL
BEGIN
return 3 --error out of range param
END
--do work here
go

Resources