TSQL using table variable for like comparison, ideally without iterating - sql-server-2008

Following the posting,
TSQL Variable With List of Values for IN Clause
I formed a table variable of varchar, e.g.
Declare #myList_1(Id varchar(2))
Insert into #myList_1
Select id from (VALUES ('x1')) AS tbl(id)
Insert into #myList_1
Select id from (VALUES ('x2')) AS tbl(id)
Insert into #myList_1
Select id from (VALUES ('x3')) AS tbl(id)
However, I need to extend this concept so that I can do something such as a "like comparison"
e.g.:
myTable.myCol like ('%' + #myList_1 + '%')
above: SSMS 2008 r2 gives error: 'Must declare the scalar variable #myList_1'
If possible, I'd like to do this without an iterator or looping construct ...

Let's assume following testing data and tables structure.
-- Create test table
CREATE TABLE [dbo].[myTable](
[Id] [int] NOT NULL PRIMARY KEY,
[myCol] [varchar](100) NULL)
GO
-- Insert test data
INSERT INTO myTable(Id, myCol)
VALUES (1, 'Bladder cancer'),
(2, 'Lung cancer'),
(3, 'Brain cancer'),
(4, 'Melanoma'),
(5, 'Breast cancer'),
(6, 'Non-Hodgkin lymphoma'),
(7, 'Cervical cancer'),
(8, 'Ovarian cancer'),
(9, 'Cardiovascular disease'),
(10, 'Nerve damage'),
(11, 'Kidney damage'),
(12, 'Eye damage'),
(13, 'Foot damage'),
(14, 'Skin conditions'),
(15, 'Alzheimer''s disease'),
(16, 'Hearing impairment')
GO
Now the actual SQL would be based on joining the table where you want to do search with table variable #myList_1
-- Create list of items to look for
Declare #myList_1 table(Id varchar(20))
Insert into #myList_1
Select id from (VALUES ('cancer')) AS tbl(id)
Insert into #myList_1
Select id from (VALUES ('Melanoma')) AS tbl(id)
Insert into #myList_1
Select id from (VALUES ('lymphoma')) AS tbl(id)
-- Do query
SELECT myTable.Id, myTable.myCol
FROM myTable
JOIN #myList_1 as ItemsList
ON myTable.myCol like '%' + ItemsList.Id + '%'
In this simple case where myCol could match just single value in the #myList_1 this should be enough, but for cases where possible that myCol could match multiple values in the #myList_1 you should add DISTINCT to the query
-- Do query
SELECT DISTINCT myTable.Id, myTable.myCol
FROM myTable
JOIN #myList_1 as ItemsList
ON myTable.myCol like '%' + ItemsList.Id + '%'

Related

Best practice of executing dynamic SQL strings via prepared statements and procedures

Background: I am building a Springboot+mySQL app that uses Spring Data JPA native queries (i.e. #Query(value = "...", nativeQuery = true) to retrieve database data.
We have to use the same SQL in every query we write to enable certain functionality (this can be seen in the example below). And wanted a way to remove this duplicate SQL and instead only declare it once. An option presented was to pass a dynamic SQL string into a stored procedure and then build a prepared statement by concatenating this dynamic SQL string with our static shared SQL string (show in example below).
Question:
This doesn't seem like a good idea to me, but I am not knowledgeable enough about databases to given the exact technical reasons. Is the below example safe, reasonable, and best-practice? Are there ways to mitigate issues with this approach, or are there other approaches to use instead?
Basic setup code:
-- create tables
CREATE TABLE docs (
id INTEGER PRIMARY KEY,
rev INTEGER NOT NULL,
content VARCHAR(30) NOT NULL
);
CREATE TABLE more_docs (
id INTEGER PRIMARY KEY,
more_content VARCHAR(30) NOT NULL
);
CREATE TABLE docs_metadata (
id INTEGER PRIMARY KEY,
letter VARCHAR(30) NOT NULL
);
CREATE TABLE metadata_nums (
id INTEGER PRIMARY KEY,
metadata_id INTEGER,
num INTEGER NOT NULL
);
-- insert some values
INSERT INTO docs VALUES (1, 1, 'abc');
INSERT INTO docs VALUES (2, 1, 'def');
INSERT INTO docs VALUES (3, 2, 'ghi');
INSERT INTO docs VALUES (4, 1, 'jkl');
INSERT INTO more_docs VALUES (1, 'aaa');
INSERT INTO more_docs VALUES (2, 'bbb');
INSERT INTO more_docs VALUES (3, 'ccc');
INSERT INTO more_docs VALUES (4, 'ddd');
INSERT INTO docs_metadata VALUES (1, 'a');
INSERT INTO docs_metadata VALUES (2, 'b');
INSERT INTO docs_metadata VALUES (3, 'c');
INSERT INTO docs_metadata VALUES (4, 'd');
INSERT INTO metadata_nums VALUES (1, 1, 5);
INSERT INTO metadata_nums VALUES (2, 1, 6);
INSERT INTO metadata_nums VALUES (3, 2, 5);
INSERT INTO metadata_nums VALUES (4, 2, 6);
INSERT INTO metadata_nums VALUES (5, 3, 5);
INSERT INTO metadata_nums VALUES (6, 3, 6);
INSERT INTO metadata_nums VALUES (7, 4, 5);
INSERT INTO metadata_nums VALUES (8, 4, 6);
Approach in question:
-- create stored procedure
DELIMITER //
CREATE PROCEDURE FILTER_EVAL (IN dynamic_statement TEXT, IN num INT, IN letter VARCHAR(1))
BEGIN
SET #dynamic_statement := CONCAT("SELECT X.* FROM (", dynamic_statement, ") X INNER JOIN (SELECT DM.*, MN.num FROM docs_metadata DM INNER JOIN metadata_nums MN ON DM.id = MN.metadata_id) M ON X.id = M.id WHERE M.num = ", num, " AND M.letter = '", letter, "'");
PREPARE prepared_statement FROM #dynamic_statement;
EXECUTE prepared_statement;
DEALLOCATE PREPARE prepared_statement;
END//
DELIMITER ;
-- fetch some values
CALL FILTER_EVAL("SELECT * FROM docs WHERE rev = 1", 5, 'b')

Stored procedure with input and output SQL

I am trying to make a stored procedure that takes a name/or number and returns a specific value for that name/number
So in this code, I am trying to write a stored procedure taht takes a company name or the cvr number and return the degree of compliance for that company
DROP DATABASE IF EXISTS DRCS;
CREATE DATABASE DRCS;
USE DRCS;
CREATE TABLE Companies (
ID INT not null,
Name varchar(255),
primary key (ID)
);
CREATE TABLE CVR (
ID INT not null,
CVR_Number INT
);
CREATE TABLE Compliance (
ID INT not null,
Complaince_level varchar(255)
);
CREATE TABLE GDPR (
ID INT not null,
GDPR_steps varchar(255)
);
INSERT INTO Companies VALUES
(1, 'TDC'),
(2, 'MAERSK'),
(3, 'LEGO'),
(4, 'SAS'),
(5, 'Carlsberg');
INSERT INTO CVR VALUES
(11, '14773908'),
(12, '32345794'),
(13, '47458714'),
(14, '56994912'),
(15, '61056416');
INSERT INTO Compliance VALUES
(21, '10%'),
(22, '20%'),
(23, '40%'),
(24, '60%'),
(25, '80%');
INSERT INTO GDPR VALUES
(31, '1. Awareness'),
(32, '2. Information you hold'),
(33, '3. Communication privacy information'),
(34, '4. Individuals rights'),
(35, '5. Subject access requests');
#HERE MY PROBLEM STARTS
DELIMITER $$
CREATE PROCEDURE DoC()
BEGIN
SELECT * FROM Companies , CVR, Compliance, GDPR;
END $$
DELIMITER ;
CALL DoC;
There is no relationship between the four tables!
Create rows with common id like id = 1,2,3,4 for all tables and then do a join and then try to list the fields you want to view.
INSERT INTO Companies VALUES
(1, 'TDC'),
(2, 'MAERSK'),
(3, 'LEGO'),
(4, 'SAS'),
(5, 'Carlsberg');
INSERT INTO CVR VALUES
(1, '14773908'),
(2, '32345794'),
(3, '47458714'),
(4, '56994912'),
(5, '61056416');
INSERT INTO Compliance VALUES
(1, '10%'),
(2, '20%'),
(3, '40%'),
(4, '60%'),
(5, '80%');
INSERT INTO GDPR VALUES
(1, '1. Awareness'),
(2, '2. Information you hold'),
(3, '3. Communication privacy information'),
(4, '4. Individuals rights'),
(5, '5. Subject access requests');
select c.id,v.cvr_Number from Companies c, cvr v where c.id = v.id
Similarly add more tables by joining with id. You don't need a procedure to this and a procedure is not designed for this.
You can make with union query for all table. But all select query of clomum count should be same.
DELIMITER $$
CREATE PROCEDURE DoC()
SELECT A.id,A.name FROM
( SELECT id as id , name as name FROM Companies
UNION ALL
SELECT id as id , name as name FROM CVR
UNION ALL
SELECT id as id , name as name FROM Compliance
UNION ALL
SELECT id as id , name as name FROM GDPR) as A
END $$
DELIMITER ;

INSTEAD OF trigger, to mimic BEFORE in Oracle

I am implementing more rigorous error logging into my current insert statements. I want to basically log the error that occurs for the individual row if there is one - keeping the information of the row (into a system table?). then i want to continue processing more rows. I have seen use of the INSTEAD OF trigger to accomplish this but wondered if anyone has more experience or knowledge than I can find here: https://technet.microsoft.com/en-us/library/ms175521(v=sql.105).aspx
right now I am just failing the whole insert and having to locate the error manually, I know ORACLE allows a 'BEFORE' trigger, but I have seen INSTEAD OF referenced as a SQL SERVER 2008 R2 (and above) alternative?? thank you for any help you can give!
Here is some example data to be inserted, I would like to log the second primarykey = 1 with values
(1,'five','six','seven')
as a duplicate key error, and then continue inserting rows with 9 and 0 :
CREATE TABLE ImportTable_Temp (
primarykey INT UNIQUE
,somedata VARCHAR(50)
,somemoredata VARCHAR(50)
,yetevenmoredata VARCHAR(50)
)
INSERT INTO ImportTable_Temp
VALUES (1, 'two', 'three', 'four'),
(2, 'two', 'three', 'four'),
(3, 'two', 'three', 'four'),
(4, 'two', 'three', 'four'),
(5, 'two', 'three', 'four'),
(6, 'two', 'three', 'four'),
(7, 'two', 'three', 'four'),
(8, 'two', 'three', 'four'),
(1, 'five', 'six', 'seven'),
(9, 'two', 'three', 'four'),
(0, 'two', 'three', 'four')
From other posts I have the general syntax for a trigger, but I would like to have more information about the error capture, perhaps reaching a threshold where the entire insert would fail perhaps at say 50% of the rows executed. I have seen people reference the deleted and inserted tables that are inherent in SQL Server's system tables? Is this true? How would I go about keeping track of how many errors have occurred as the process is occurring? Thanks!
--==================================================
--create initial tables for data and error logging
--==================================================
CREATE TABLE ImportTable (primarykey INT UNIQUE,
somedata VARCHAR(50),
somemoredata VARCHAR(50),
yetevenmoredata VARCHAR(50));
CREATE TABLE #ErrorTable (LogID INT NOT NULL IDENTITY PRIMARY KEY,
ImportRowID INT NOT NULL,
newsomedata VARCHAR(50),
newsomemoredata VARCHAR(50),
newyetevenmoredata VARCHAR(50),
SomeERRORValue VARCHAR(1000) NULL,
oldsomedata VARCHAR(50),
oldsomemoredata VARCHAR(50),
oldyetevenmoredata VARCHAR(50));
--=====================================================
--Creation of the Instead of Trigger with Error logging
--=====================================================
GO
CREATE TRIGGER TR_ImportTable_Insert ON ImportTable
INSTEAD OF INSERT
AS
IF ##rowcount = 0
RETURN
-- Violation of PRIMARY KEY
IF EXISTS (
SELECT *
FROM Inserted AS I
INNER JOIN ImportTable IT
ON IT.primarykey = I.primarykey
)
INSERT INTO #ErrorTable (ImportRowID, newsomedata, newsomemoredata, newyetevenmoredata, oldsomedata, oldsomemoredata, oldyetevenmoredata, SomeERRORValue)
SELECT I.primarykey, I.somedata, I.somemoredata, I.yetevenmoredata, IT.somedata, IT.somemoredata, IT.yetevenmoredata, 'Violation of Primary Key'
FROM Inserted AS I
INNER JOIN ImportTable IT
ON IT.primarykey = I.primarykey
--Insert only valid rows to the ImportTable
INSERT INTO ImportTable
SELECT *
FROM Inserted AS I
WHERE I.primarykey NOT IN (
SELECT primarykey
FROM ImportTable
)
--=====================================================
--The trigger works if I issue the command FOR EACH ROW
--=====================================================
GO
BEGIN
INSERT INTO ImportTable
VALUES (1, 'two', 'three', 'four'),
(2, 'eight', 'nine', 'ten'),
(3, 'eleven', 'twelve', 'thirteen');
END
GO
INSERT INTO ImportTable
VALUES (1, 'five', 'six', 'seven');
INSERT INTO ImportTable
VALUES (4, 'fourteen', 'fifteen', 'sixteen');
--====================================================
--I want it to work also for BULK INSERT violations
--Please comment out above statement insert and
--Uncomment below statement to see behavior I mean
--====================================================
-- INSERT INTO ImportTable
-- VALUES (1,'two','three','four'),
-- (1,'five','six','seven'),
-- (2,'eight','nine','ten'),
-- (3,'eleven','twelve','thirteen');
-- INSERT INTO ImportTable
-- VALUES (2,'two','three','four'),
-- (4,'five','six','seven'),
-- (4,'eight','nine','ten');
--=====================================================
--Select statement to view operations, if they succeed
--=====================================================
/*
SELECT * FROM ImportTable;
SELECT * FROM #ErrorTable;
*/
--==========================================================
--Drop all temp tables and triggers to allow serializability
--Execute before testing different inserts functionality
--==========================================================
/*
DROP TABLE ImportTable;
DROP TABLE #ErrorTable;
*/
Thanks goes out to http://sqlmag.com/t-sql/tricks-instead-triggers for the help with the above code!

i need an sp to select or update my tables and for that i have to enter multiple values for single variable how can i do that?

desperately need an sp to pass mutiple values for the single variable like #list is a variable and the values I'm putting for it are '1,3,4,5,66' and I need information from the table realated to these id's:
SELECT T.C.value('.', 'NVARCHAR(100)') AS [id]
INTO #tblPersons
FROM (SELECT CAST ('<Name>' + REPLACE(#empid, ',', '</Name><Name>') + '</Name>' AS XML) AS [Names]) AS A
cross APPLY Names.nodes('/Name') as T(C)
I'm using this in my sp but I'm getting difficulty for passing this for the mutiple values.
Have you thought about using table variables to pass data to a stored procedure. Example:
Setup
CREATE TYPE EmpIdValuesType AS TABLE
(
[EmpID] [int]NOT NULL
)
CREATE TABLE Employee
(
EmpID INT,
Name varchar(20)
)
INSERT INTO Employee
Values
(1, 'test1'),
(2, 'test2'),
(3, 'test3'),
(4, 'test4'),
(5, 'test5'),
(6, 'test6'),
(7, 'test7');
Create Procedure usp_GetEmployees
(
#TableVariable EmpIdValuesType READONLY
)
AS
SELECT *
FROM Employee
INNER JOIN #TableVAriable TV
ON Employee.EmpId = TV.EmpId
Now you can insert rows into a temporary table variable of type EmpIdValuesType and pass the variable to the stored procedure:
Calling the Stored Procedure
DECLARE #empIds AS EmpIdValuesType
INSERT INTO #empIds(EmpID) Values (1), (2), (5)
Exec usp_GetEmployees #empIds;
And here are the results:
SQLFiddle

Validate email addresses in Mysql

This query creates a mysql view that captures bad email address formats in one table. So if a row is inserted in that has rtrrg.com as a email it will be recorded in the view. My question is, how do I make the view track more than one table. A second table.
The SQL
CREATE VIEW `invalid_emails` AS
select `table_with_email_column`.`email` AS `invalidemail`
from `table_with_email_column`
where ((locate(_latin1'', ltrim(rtrim(`table_with_email_column`.`email`))) <> 0)
or (left(ltrim(`table_with_email_column`.`email`), 1) = _latin1'#')
or (right(rtrim(`table_with_email_column`.`email`), 1) = _latin1'.')
or ((locate(_latin1'.', `table_with_email_column`.`email`,locate(_latin1'#', `table_with_email_column`.`email`)) - locate(_latin1'#', `table_with_email_column`.`email`)) <= 1)
or ((length(ltrim(rtrim(`table_with_email_column`.`email`))) - length(replace(ltrim(rtrim(`table_with_email_column`.`email`)), _latin1'#', _latin1''))) <> 1)
or (locate(_latin1'.', reverse(ltrim(rtrim(`table_with_email_column`.`email`)))) < 3)
or (locate(_latin1'.#', `table_with_email_column`.`email`) <> 0)
or (locate(_latin1'..', `table_with_email_column`.`email`) <> 0));
You can use a pure SELECT to validate Email Addresses:
SELECT * FROM `users` WHERE `email` NOT REGEXP '^[^#]+#[^#]+\.[^#]{2,}$';
And now for your question of tracking multiple tables, you can use comma seperated table names right?
SELECT * FROM `users`, `customers`, `clients`
WHERE `email` NOT REGEXP "^[a-zA-Z0-9][a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]*?[a-zA-Z0-9._-]?#[a-zA-Z0-9][a-zA-Z0-9._-]*?[a-zA-Z0-9]?\\.[a-zA-Z]{2,63}$";
For the proper email validation, you can use this regex as bellow:
SELECT
*
FROM
`school`
WHERE
`email` NOT REGEXP '^[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9._-]#[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]\\.[a-zA-Z]{2,63}$';
Simple SELECT statement is sufficient, for example:
SELECT * FROM user WHERE email NOT
REGEXP '^[a-zA-Z0-9][+a-zA-Z0-9._-]*#[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]*\\.[a-zA-Z]{2,4}$'
This query handles the Gmail addresses with + sign and addresses where the host is a single letter.
You can use a UNION in the VIEW but then you have to repeat all the WHERE statement which gives you redundant code. So you would make a helper VIEW that makes you a UNION and then apply the WHERE clause.
Demo here: SQL Fiddle Demo.
That would apply to your SQL somehow like this (untested);
CREATE VIEW `invalid_emails_helper` AS
select `table_with_email_column`.`email` AS `invalidemail`
from `table_with_email_column`
union
select `table_with_email_column`.`email`
from `second_table_with_email_column`
CREATE VIEW `invalid_emails` AS
select `invalidemail` as `email`
from `invalid_emails_helper` as `table_with_email_column`
where ((locate(_latin1'', ltrim(rtrim(`table_with_email_column`.`email`))) <> 0)
or (left(ltrim(`table_with_email_column`.`email`), 1) = _latin1'#')
or (right(rtrim(`table_with_email_column`.`email`), 1) = _latin1'.')
or ((locate(_latin1'.', `table_with_email_column`.`email`,locate(_latin1'#', `table_with_email_column`.`email`)) - locate(_latin1'#', `table_with_email_column`.`email`)) <= 1)
or ((length(ltrim(rtrim(`table_with_email_column`.`email`))) - length(replace(ltrim(rtrim(`table_with_email_column`.`email`)), _latin1'#', _latin1''))) <> 1)
or (locate(_latin1'.', reverse(ltrim(rtrim(`table_with_email_column`.`email`)))) < 3)
or (locate(_latin1'.#', `table_with_email_column`.`email`) <> 0)
or (locate(_latin1'..', `table_with_email_column`.`email`) <> 0));
And yes, the query to check the e-mail address using a regex as can easily found everywhere in the internet simplifies it further.
SELECT
*
FROM
users
WHERE
email NOT REGEXP ‘ ^[ a - zA - Z0 - 9 ][ a - zA - Z0 - 9._ -]*[ a - zA - Z0 - 9 ]#[ a - zA - Z0 - 9 ][ a - zA - Z0 - 9._ -]*[ a - zA - Z0 - 9 ]\.[ a - zA - Z ]{ 2,
63 } $’
select EmailAddress from FindInvalidEmailAddressDemo
-> where EmailAddress NOT LIKE '%_#_%._%';
With MySQL 9 you can create a check constraint now that will validate all data stored in the email address column. Here is an ALTER TABLE statement:
ALTER TABLE `user`
ADD CONSTRAINT `user.email_validation`
CHECK (`email` REGEXP "^[a-zA-Z0-9][a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]*?[a-zA-Z0-9._-]?#[a-zA-Z0-9][a-zA-Z0-9._-]*?[a-zA-Z0-9]?\\.[a-zA-Z]{2,63}$");
My solution for finding invalid emails:
SELECT * FROM `tbl_email` WHERE `email` NOT REGEXP '^[a-zA-Z0-9]+[a-zA-Z0-9._-]*#[a-zA-Z0-9]+[a-zA-Z0-9._-]*\.[a-zA-Z0-9]{2,63}$';
Once only regexp suggestted doesn't consider all errors, I complete on my own function. See the comments into code.
DELIMITER $$
CREATE OR REPLACE function fn_DOC_Validar_EMail ( pStrEMail VARCHAR(200) )
RETURNS BIT
BEGIN
declare lIntValid bit;
set lIntValid = 0;
SELECT 1 into lIntValid
Where pStrEMail REGEXP '^[a-zA-Z0-9][a-zA-Z0-9.!#$%&\'*+-/=?^_`{|}~]*?[a-zA-Z0-9._-]?#[a-zA-Z0-9][a-zA-Z0-9._-]*?[a-zA-Z0-9]?\\.[a-zA-Z]{2,63}$'
and pStrEMail not like '%[^a-z0-9#._-]%' -- not allow characters differents: a-z 0-9 # . _ -
and pStrEMail not like '%#%#%' -- not allow two #
and pStrEMail not like '%.#%' -- not allow .#
and pStrEMail not like '%..%' -- not allow ..
and pStrEMail not like '%.' -- not allow . (dot) at end
and pStrEMail like '%_#_%_.__%' -- not allow short, i.e., a#a.com
and pStrEMail not LIKE '%^%' -- not allow character ^
and pStrEMail not LIKE '%\%%' -- not allow character %
;
return lIntValid ;
END;
$$
Use the samples bellow to Test your function.
Select Sequencial, email, fn_DOC_Validar_EMail(EMail) from TEMP_Emails;
Create table TEMP_Emails
(
Sequencial int,
Email varchar(200)
);
-- invalids
insert into TEMP_Emails values (1, '#teste.com'); -- Start with #
insert into TEMP_Emails values (2, 'josue#teste'); -- with out domain
insert into TEMP_Emails values (3, 'jo ue#teste'); -- espace
insert into TEMP_Emails values (4, 'jo"ue#teste'); -- quotes
insert into TEMP_Emails values (5, 'jo$ue#teste'); -- special Character
insert into TEMP_Emails values (6, 'josue^teste#teste.com'); -- special Character
insert into TEMP_Emails values (7, 'josue]teste#teste.com'); -- special Character
insert into TEMP_Emails values (8, 'josue%teste#teste.com'); -- special Character
insert into TEMP_Emails values (9, 'josue#.teste.com'); -- #.
insert into TEMP_Emails values (10, 'josue##teste.com'); -- 2 x #
insert into TEMP_Emails values (11, 'josue#teste#teste.com'); -- 2 x #
insert into TEMP_Emails values (12, 'josue.#teste.com'); -- .#
insert into TEMP_Emails values (13, 'josue#teste..com'); -- ..
insert into TEMP_Emails values (14, 'josue#teste.ad.'); -- . at final
--OK: Valids
insert into TEMP_Emails values (101, 'josue#teste.com.br');
insert into TEMP_Emails values (102, 'jo.sue#teste.com.br');
insert into TEMP_Emails values (103, 'josue#teste.com');
insert into TEMP_Emails values (104, 'josue.teste#teste.com');
insert into TEMP_Emails values (105, 'josue_teste#teste.com');
insert into TEMP_Emails values (106, 'josue-teste#teste.com');
insert into TEMP_Emails values (107, 'josue#dba-pro.com');
insert into TEMP_Emails values (108, 'josue#dba.pro.com');
insert into TEMP_Emails values (109, 'josue2017#teste.com');
insert into TEMP_Emails values (110, '2022#2022.com');
Select Sequencial, email, fn_DOC_Validar_EMail(EMail) from TEMP_Emails;