EXEC %%System().FireTrigger - sql-server

I was just wondering what is this?
EXEC %%System().FireTrigger(ID = 225, ID = 102, ID = 0, ID = 0, Value = #server,
ID = -1, ID = 0, ID = 0, Value = NULL,
ID = 7, Value = #server, Value = #srvproduct2, Value = #provider, Value = #datasrc, Value = #location, Value = NULL, Value = #catalog)
I have been trying to look for it in mssql but I cant find it, what does it mean? I know EXEC is used to execute stored procedure, but what is %%System()?
and what is FireTrigger? is it an embedded command in the system? external dll? been trying to Google it but it seems to be vague at the moment.

This is an internal mechanism that is sometimes exposed but you can't call it yourself and it is undocumented.

Related

Always Encrypted - Parameters

Have set up Always Encrypted for my table columns at server side.
From a C++ client, I use the below connection string to connect to the database:
CString connString = L"Driver={ODBC Driver 17 for SQL Server};Server=192.122.200.200,1433;Encrypt=no;Trusted_Connection=no;ColumnEncryption=Enabled;DATABASE=AlwaysEncrypted;UID=sa;PWD=;";
From the same client I invoke below command to insert data:
CString csQStrInsert = L"declare #val1 int = 3; declare #val2 int = 3; insert into [dbo].[Table_AlwaysEncrypted] ([col1], [col2]) values (#val1, #val2);";
pDatabase->ExecuteSQL(csQStrInsert);
Unfortunately the query fails with below error:
pEX->m_strError = L"Encryption scheme mismatch for columns/variables '#val1'. The encryption scheme for the columns/variables is (encryption_type = 'PLAINTEXT') and the expression near line '1' expects it to be DETERMINISTIC, or PLAIN TEXT.
What am I doing wrong?
You cannot use local variables for Always Encrypted columns, they must come from client-side parameters. In SSMS it works because SSMS parses your script and pulls out the variables into parameters, but in C++ or other clients you must parameterize it yourself.
For example, the below code is used as an example on Microsoft's website, see there for more info on how to use Always Encrypted:
SQL_DATE_STRUCT date;
SQLLEN cbdate; // size of date structure
SQLCHAR SSN[12];
strcpy_s((char*)SSN, _countof(SSN), "795-73-9838");
SQLWCHAR* firstName = L"Catherine";
SQLWCHAR* lastName = L"Abel";
SQLINTEGER cbSSN = SQL_NTS, cbFirstName = SQL_NTS, cbLastName = SQL_NTS;
// Initialize the date structure
date.day = 10;
date.month = 9;
date.year = 1996;
// Size of structures
cbdate = sizeof(SQL_DATE_STRUCT);
SQLRETURN rc = 0;
string queryText = "INSERT INTO [dbo].[Patients] ([SSN], [FirstName], [LastName], [BirthDate]) VALUES (?, ?, ?, ?) ";
rc = SQLPrepare(hstmt, (SQLCHAR *)queryText.c_str(), SQL_NTS);
//SSN
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 11, 0, (SQLPOINTER)SSN, 0, &cbSSN);
//FirstName
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 50, 0, (SQLPOINTER)firstName, 0, &cbFirstName);
//LastName
rc = SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 50, 0, (SQLPOINTER)lastName, 0, &cbLastName);
//BirthDate
rc = SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT, SQL_C_TYPE_DATE, SQL_TYPE_DATE, 10, 0, (SQLPOINTER)&date, 0, &cbdate);
rc = SQLExecute(hstmt);
As you can see, SQLBindParameter is used to add parameters to the query. You cannot use either literals or SQL local variables to insert or compare with encrypted columns, as the server has no access to the decrypted data.
The client driver needs to have access to the relevant certificate.

not cursor at all with err msg :Cursorfetch: The number of variables declared in the INTO list must match that of selected columns

I'm trying to run simple update , not cursor at all :) in Microsoft SQL Server
and I'm getting a strange error message .
Here is the update statement:
update [MaintenancePortal].[dbo].maz_batia
set mok_sap_num = '00001009999' ,
mok_sap_work_order = '00000123123',
mok_sap_status = 'אאאאא',
mok_sap_status_work_order = 'בבבבב',
-- mok_equ_bz_description = NULL,
mok_location_description = 'גגג>ב8>גגג',
mok_work_order_cost_center = 'רררר',
mok_work_order_date = '2020-03-11',
mok_work_order_description = 'אבגאבגאבג' ,
mok_sap_tibco_status = 'SAP statuses updated',
mok_user_open = 'מממממ'
mok_department_desc = 'גגג>ב8>גגג'
where mok_sap_num = '00001009999'
This is the full error msg:
Msg 16924, Level 16, State 1, Procedure SendMail, Line 63 [Batch Start Line 76]
Cursorfetch: The number of variables declared in the INTO list must match that of selected columns.
What can be the problem ? I'm going crazy :(
Thanks

snowflake jdbc paramter returning VARCHAR for all datatypes

Snowflake JDBC driver is reporting parameter metadata for all the datatypes as VARCHAR. Is there any way to overcome this problem?
DDL:-
CREATE TABLE INTTABLE(INTCOL INTEGER)
Below is the output from Snowflake ODBC Driver
SQLPrepare:
In:StatementHandle = 0x00000000021B1B50, StatementText = "INSERT INTO INTTABLE(INTCOL) VALUES(?)", TextLength = 42
Return: SQL_SUCCESS=0
SQLDescribeParam:
In:StatementHandle = 0x00000000021B1B50, ParameterNumber = 1, DataTypePtr = 0x00000000001294D0, ParameterSizePtr = 0x0000000000126950,DecimalDigits =0x0000000000126980, NullablePtr = 0x00000000001269B0
Return: SQL_SUCCESS=0
Out:*DataTypePtr = SQL_VARCHAR=12, *ParameterSizePtr = 16777216, *DecimalDigits = 0, *NullablePtr = SQL_NULLABLE=1
Below is Output with Snowflake JDBC Driver.
PreparedStatement ps = c.prepareStatement("INSERT INTO INTTABLE(INTCOL) VALUES(?)");
ParameterMetaData psmd = ps.getParameterMetaData();
for(int i=1 ;i<=psmd.getParameterCount(); i++) {
System.out.println(psmd.getParameterType(i)+ " " + psmd.getParameterTypeName(i));
}
Output:-
12 text
Thank you for adding more information to your thread. I still may be doing a little guesswork though.
If you are trying to change the table values type from Varchar, and there are no values in it, you can drop the table, then re-recreate it.
If you want to ALTER what is already in the table try altering the table first: Manual Reference
There is also the CREATE OR REPLACE TABLE(col , col 2 ) that takes care of both.
Is this what you are looking for?

Manipulating the list of data from stored procedure to be used in another stored procedure

Currently I'm writing a stored procedureusing T-SQL in SQL Server. My script contains code to run another stored procedure to get list of data from a table. I want to manipulate the data, using the list of data to modify them for another purpose (e.g. summing up a column and adding more lists of data) from the stored procedure. A way that I know is to create a temporary table. But after that, I'm not so sure. Please help. thanks.
This is my code:
ALTER PROCEDURE [dbo].[AJU_Rpt_ARAgingSp]
(#Slsman_Starting slsmantype = NULL,
#Slsman_Ending slsmantype = NULL,
#Custnum_Starting custnumtype = NULL,
#Custnum_Ending custnumtype = NULL,
#CustType endusertypetype = NULL,
#CutOff_Date datetype = NULL,
#SumToCorp ListYesNoType = NULL, -- >> 0 = individual, 1 = corp customer
#ShowActive ListYesNoType = NULL, -- >> 0 = all trx, 1 = active only
#TransDomCurr ListYesNoType = NULL, -- >> 0 = dont convert, 1 = convert to local currency
#AgingBasis ArAgeByType = NULL, -->> i = invoice date, d = due date
#LeftToRight ListYesNoType = NULL, -- >> 0 = right to left, 1 = left to right
#CurrSite NVARCHAR(8),
#ShowDetailInfo NVARCHAR(1) = NULL)
AS
BEGIN
SET NOCOUNT ON
IF ISNULL(#CurrSite ,'') = ''
SET #CurrSite = (SELECT TOP 1 site_ref FROM parms_mst)
DECLARE #v_StartDate DateType
SET #Slsman_Starting = ISNULL(#Slsman_Starting, dbo.LowCharacter())
SET #Slsman_Ending = ISNULL(#Slsman_Ending, dbo.HighCharacter())
SET #Custnum_Starting = ISNULL(#Custnum_Starting, dbo.LowCharacter())
SET #Custnum_Ending = ISNULL(#Custnum_Ending, dbo.HighCharacter())
SET #v_StartDate = dbo.LowDate()
SET #CutOff_Date = GETDATE()
EXEC dbo.ApplyDateOffsetSp #v_StartDate OUT, NULL, 0
EXEC AJU_Rpt_DebtorSp
#CustNumStart = #Custnum_Starting
,#CustNumEnd = #Custnum_Ending
,#DistDateStart = #v_StartDate
,#DistDateEnd = #CutOff_Date
,#CurrCodeStart = NULL
,#CurrCodeEnd = NULL
,#SlsmanStart = #Slsman_Starting
,#SlsmanEnd = #Slsman_Ending
,#TerritoryStart = NULL
,#TerritoryEnd = NULL
,#CustTypeStart = NULL
,#CustTypeEnd = NULL
,#SiteGroup = #CurrSite
,#ConsolidatePayment = NULL
,#DisplayResult = 1
END
Since the initial result table is temporarily needed, you could do as follows:
In the invoking procedure, create a table variable with identical structure as returned by the invoked procedure,
Write within the invoking procedure a statement like the following:
INSERT INTO #_Tempo_Table
EXEC Invoked_Procedure (<params>) ;
Within the invoked procedure issue a SELECT that will return the records set.
If, in the other hand, you need to pass the initial table to the invoked procedure:
Create a type with a structure identical to the table that needs to be shared,
Add to the invoked procedure an argument of the type you just created (must be declared as READONLY),
Once you have the table with data within the invoking procedure, make the call to the invoked procedure passing the table variable as argument.
This methods will render the best performance (here I'm assuming that you are not passing a table with millions of records; if you do, it will still be the fastest way though you might need a lot of memory).

PostgreSQL 8.3.11 locked; orphaned pg_toast database object recovery

Howdy Slack Overflowvians.
So I came across this PostgreSQL server running 8.3.11 (yeah I know), that was in a locked state with:
ERROR: database is not accepting commands to avoid wraparound data loss in database "postgres"
HINT: Stop the postmaster and use a standalone backend to vacuum that database.
Normally the auto vaccum daemon (autovacuum=on), would handle this, but because the following four TOAST (allows storage of large field values 8 kB slices, like bread), database object. But the XID of this database never was reset because of these corrupt database objects.
Below is a snippet of the output when running the server in single-user mode with the admin user:
SELECT oid, relname, age(relfrozenxid) FROM pg_class WHERE relkind = 't' ORDER BY age(relfrozenxid) DESC LIMIT 4;
----
1: oid = "2421459" (typeid = 26, len = 4, typmod = -1, byval = t)
2: relname = "pg_toast_2421456" (typeid = 19, len = 64, typmod = -1, byval = f)
3: age = "2146484084" (typeid = 23, len = 4, typmod = -1, byval = t)
----
1: oid = "2421450" (typeid = 26, len = 4, typmod = -1, byval = t)
2: relname = "pg_toast_2421447" (typeid = 19, len = 64, typmod = -1, byval = f)
3: age = "2146484084" (typeid = 23, len = 4, typmod = -1, byval = t)
----
1: oid = "2421435" (typeid = 26, len = 4, typmod = -1, byval = t)
2: relname = "pg_toast_2421432" (typeid = 19, len = 64, typmod = -1, byval = f)
3: age = "2146484084" (typeid = 23, len = 4, typmod = -1, byval = t)
----
1: oid = "2421426" (typeid = 26, len = 4, typmod = -1, byval = t)
2: relname = "pg_toast_2421423" (typeid = 19, len = 64, typmod = -1, byval = f)
3: age = "2146484084" (typeid = 23, len = 4, typmod = -1, byval = t)
Notice the age is well above the vacuum_freeze_min_age (value set after a successful VACUUM), on this server and thus why it was issuing the original errors above. The above was AFTER running a VACUUM FULL; all other tables fine.
SELECT relfilenode FROM pg_class WHERE oid=2421459;
So when we looked on disk (used the pg_class.relfilenode value for each table above) the toast table's file was missing:
$ find /var/lib/pgsql/data/ -type f -name '2421426' | wc -l # Bad toast
0
and when we looked on disk at the index of the toast
SELECT relfilenode FROM pg_class WHERE (select reltoastidxid FROM pg_class WHERE oid=2421459)
$ find /var/lib/pgsql/data/ -type f -name '2421459' | wc -l # Bad toast's index
0
We then tried to find the table that the bad toast record is related to with:
SELECT * FROM pg_class WHERE reltoastrelid=2421459;
got 0 results for each table above! There are no tables for the VACUUM command to reset the XID of these relations.
When we checked the pg_depend table and found that these TOAST tables have NO references:
SELECT * FROM pg_depend WHERE refobjid IN(2421459,2421450,2421435,2421426)
Question
Can you delete the bad TOAST table and TOAST table indexes from the
pg_class table (e.g. DELETE FROM pg_class where oid=2421459)
Are there any other tables that we also need to remove the relation
from?
Could we just create a temp table and link it to the TOAST's
index's oid?
Example for #3 above:
CREATE TABLE adoptedparent (colnameblah char(1));
UPDATE pg_class SET reltoastrelid=2421459 WHERE relname='adoptedparent';
VACUUM FULL VERBOSE adoptedparent
EDIT:
select txid_current() is 3094769499 so these tables were corrupted a long time ago. We don't need to recover the data. We are running ext4 file system on Linux 2.6.18-238.el5. We checked the relevant lost+found/ directories and the files were not there.
Just for the home audience, in this particular case the resolution was to edit pg_class directly. And update the server to a supported version of Postgres, of course!
Specific answers:
Yes you can, although in most cases it's better to create an empty table, attach the toast relation to that table, add the pg_depend entries, and drop the table. In this case, that didn't make sense because there were truly no other objects depending on those toast tables.
Usually toast tables also have an index in pg_index, and entries in pg_depend. These did not.
See above.

Resources