December 2007 - Posts

SQL lietotāju masveida dzēšana

Nezinu, cik bieži (vai reti) gadās sastapt nepieciešamību izdzēst vairākus datubāzes lietotājus. Tā kā man šorīt darbā šāda vajadzība radās un ātrumā nevarēju iedomāties pareizos atslēgas vārdus, lai atrastu skriptu, kas veic šo darbību, tad nācās patērēt nedaudz laika, lai tādu uzrakstītu.

Tātad, ideja ir vienkārša. Ņemam lietotājus no sistēmas skata sys.sysusers, atfiltrējam pēc kādiem kritērijiem dzēsīsim. Sasaistam rezultātu ar sys.schemas skatu, lai pārbaudītu, vai lietotājs nav saimnieks kādai shēmai. Šāda pārbaude ir nepieciešama tādēļ, ka MS SQL serveris neļauj dzēst lietotājus, kuriem ir kādas shēmas saimnieki. Tālāk jau paliek "ģelo tehņiki".

Rezultāta skripts:

/********************************************************************
* SP for droping users from database *
* (c) 2008 Ivars "PiRX" Āriņš *
* e-mail: ivars_a@inbox.lv *
* !!!NB:Use it on your own risk!!! *
*==================================================================*
* Usage: *
* EXEC dbo.CleanUsers *
* @WhereClause = '' *
* @ExecDrop = '' ; *
* Prameters: *
* @WhereClause - WHERE clause for user filtering from sys.sysusers *
* @ExecDrop - Indicates whether DROP actualy must be executed *
* (Y - exec DROP, any other value - just simulate) *
********************************************************************/

CREATE PROCEDURE dbo.CleanUsers
WhereClause
nvarchar(300),
@ExecDrop nchar(1)
AS
BEGIN
SET NOCOUNT ON

IF NOT
@ExecDrop = 'Y'
PRINT 'Running in simulation mode';

CREATE TABLE #FilteredUsers (id int);

DECLARE @UsersSql nvarchar(400);
SET @UsersSql = 'INSERT INTO #FilteredUsers SELECT uid FROM sys.sysusers ';

IF LEN(@WhereClause) > 0
SET @WhereClause = 'WHERE ' + @WhereClause + ';';

SET @UsersSql = @UsersSql + @WhereClause;

PRINT 'Filtering users using query:';
PRINT ' SELECT uid FROM sys.sysusers ' + @WhereClause
EXEC(@UsersSql);

DECLARE curs_users CURSOR LOCAL FORWARD_ONLY
FOR SELECT DISTINCT
u_id = u.uid, --id
u_name = u.name,
s_id = s.schema_id,
s_name = s.name,
s_objects = (SELECT COUNT(*) FROM sys.all_objects o WHERE o.schema_id = s.schema_id)
FROM #FilteredUsers f
INNER JOIN sys.sysusers u ON f.id = u.uid
LEFT JOIN sys.schemas s ON s.principal_id = u.uid;

OPEN curs_users;

DECLARE @u_id int,
@u_name nvarchar(255),
@s_id int,
@s_name nvarchar(255),
@s_objects int;

FETCH NEXT FROM curs_users INTO @u_id, @u_name, @s_id, @s_name, @s_objects;

WHILE @@FETCH_STATUS = 0
BEGIN
--DROP schema if exists and containts no objects
IF @s_name IS NOT NULL
IF
(@s_objects = 0)
BEGIN
PRINT
'Droping schema ' + @s_name;
IF @ExecDrop = 'Y'
EXEC ('DROP SCHEMA [' + @s_name + '];');
SET @s_objects = 0;
END
--DROP user if doesn't own any objects
IF (@s_objects > 0)
PRINT 'Not droping user ' + @u_name + ' because owned schema ' + @s_name + ' contains '
+
CAST(@s_objects AS nvarchar(10)) + ' object(s)';
ELSE
BEGIN
PRINT
'Droping user ' + @u_name;
IF @ExecDrop = 'Y'
EXEC ('DROP USER [' + @u_name + '];');
END

FETCH NEXT FROM
curs_users INTO @u_id, @u_name, @s_id, @s_name, @s_objects;
END

CLOSE
curs_users;
DEALLOCATE curs_users;

DROP TABLE #FilteredUsers
END
GO

Procedūru izsaucot, tai nodod divus parametrus, @WhereClause, kurā norāda derīgu SQL WHERE nosacījumu (bez atslēgvārda WHERE) un @ExecDrop, ar kuru norāda, vai tiešām izpildīt lietotāju un shēmu dzēšanu, vai tika simulēt skripta darbību, neizpildot DROP operāciju.

Piemēram, lai izdzēstu visus lietotājus ar Windows autentifikāciju, kuru lietotājvārdi nestaur Ivars, skripts ir jāpalaiž šādi:

--Simulācija
EXEC dbo.CleanUsers
@WhereClause
= N'isntuser = 1 AND name NOT LIKE ''%Ivars%''',
@ExecDrop = 'N';
GO

--Izpilde
EXEC dbo.CleanUsers
@WhereClause
= N'isntuser = 1 AND name NOT LIKE ''%Ivars%''',
@ExecDrop = 'Y';
GO

P.S. Nepretendēju uz T-SQL guru statusu, tāpēc pieļauju, ka šo visu varētu uzrakstīt labāk. Manām vajadzībām derēja arī šādi.


Laikam jau zemrindas piezīmes man sāk kļūt par ieradumu. Nekas, būs konsistents veids, kā informēt par dažādām bloga saimnieciskajām lietām. Joprojām gaidu jebkādus komentārus un atsauksmes par rakstīto.

Šodienas ziņa ir tāda, ka esmu pieslēdzis FeedBurner statistiku un tāpēc ar pirmdienu atslēgšu tiešo RSS plūsmu. Tāpēc, lūdzu, pārslēdziet savus lasītājus uz http://feeds.feedburner.com/IvaraBlogs

Danger! High voltage!

Sveiks, Lasītāj!

Cilvēku vienmēr ir vilinājis viss jaunais un neiepazītais, tādēļ arī es, pēc tam, kad pie Denisa Gobo uzzināju par rīku ar elektrisku nosaukumu, nevarēju atturēties nepamēģinājis. Šodien stāstītšu par jaunu instrumentu, radītu Microsoft Live laboratorijā un sauktu Volta. Atrast to var pēc adreses http://labs.live.com/volta/.

Kas tad ir Volta? Kā paši autori izsakās, tad Volta ir eksperimentāls rīku kopums, kuru izstrādātāji var izmantot, lai veidotu standartiem atbilstošus vairākrindu/vairākslāņu (multi-tier) tīmekļa risinājumus, izmantojot esošās .NET valodas, bibliotēkas un rīkus. (Volta FAQ). Izmantojot Volta ir iespējams aplikāciju izstrādāt, neņemot vērā to, ka brīdī, kad tā tiks "palaista gaisā", daļa pienākumu tiks sadalīta starp diviem slāņiem (t.i. klientu un serveri).

Lai gan daļa no avotiem, kas raksta par Volta, kā galveno bonusu min faktu, ka .NET aplikācijas ir iespējams "pārkompilēt" par JavaScript kodu, patiesībā šis rīks dara daudz vairāk. Lai to saprastu, apskatīsim nedaudz sīkāk lietas, kas notiek "zem kapota". Kā prezentē Volta izstrādātāji, tad šis rīku komplekts ir paredzēts esošā koda deklaratīvai sadalīšanai starp slāņiem. Pārtulkojot latviski, tas nozīmē, ka izstrādes laikā nav jāuztraucās par to, kurš koda gabals kurā slānī darbosies. Vienkārši, brīdī, kad aplikācija ir pietiekami nobriedusi, lai sāktu to dalīt starp slāņiem, nepieciešams klases un/vai metodes nomarķēt ar atbilstošajiem atribūtiem un par tālāko parūpēsies Volta. Šeit arī parādās galvenā atšķirība starp Volta un GWT. Ja GWT galvenokārt kompilē no Java uz JavaScript, tad Volta  galvenais pielietojums ir koda dalīšana starp dažādiem lietojuma slāņiem, un to var izmantot arī tradicionālo desktop lietojumprogrammu pārveidošanai.

Tā, kā Volta darbojas MSIL līmenī, tad teorētiski nav nozīmes, kāda valoda tiek izmantota izstrādei. Praksē, gan lietas nav tik rožainas un, teiksim, tīmekļa aplikācijās, VB.NET netiek atbalstīts tik labi, kā C#. Tas esot saistīts ar to, ka brīdī, kad MSIL kods tiek pārkompilēts uz JavaScript, pilnībā netiek uzturēta visa BCL funkcionalitāte, un daži no neatbalstītajiem tipiem esot nepieciešami daļai VB funkcionalitātes.

 


 

Izmantotie resursi, a.k.a obligātā literatūra:

  1. Volta Home
  2. Microsoft architect compares Volta and Google’s GWT
  3. Exploring New Web Frameworks - Part 1 - Volta
  4. Volta videos on channel9
  5. Volta (Denis Gobo)
  6. Erik Meijer, principal architect for Microsoft, discusses how Volta furthers Microsoft’s innovation in Software + Services

Postskripta vietā.

Dārgo Lasītāj! Ja Tev ir pieticis pacietības šo izlasīt, tad es būšu ļoti pateicīgs par komentāru. Jo, vismaz man, atgriezeniskā saite ir ļoti svarīga un mani interesē Jūsu viedokļi. Šobrīd domāju, ka varētu veidot nelielu rakstu sēriju par Volta, apskatot izmantošanu kā tīmekļa, tā arī tradicionālajās desktop lietojumprogrammās, bet nezinu, vai tas Jūs interesē.

Paldies!
Ivars

How to shoot yourself in the foot with nullable types and SQL types *

Labvakar!

Šovakar vēlos jums pastāstīt par kādu lietu, kuru, iespējams, daži jau uzskata par novecojušu. Tomēr ne visi jau ir pārgājuši uz .NET platformas jaunākajām versijām, kā arī jebkurā laikā katram no mums var sanākt uzturēt legacy kodu. Tāpēc pastāstīšu par kādu .NET SQL datu tipu īpatnību, ar kuru ne pārāk sen saskāros.

Lai iepazīstinātu ar problēmu, varētu sarīkot nelielu konkursu, pajautājot, kāds rezultāts būs šādam kodam, gadījumā, ja no datubāzes atgriezīs NULL vērtību (atbilde jāsniedz, nepārbaudot ar programmu):

String output = SomeMethodThatReturnsDbResultWhichIsNull() ?? "Datubāzē nav datu";
Console.WriteLine(output);

Pirmajā brīdī liekas, ka ar kodu viss ir kārtībā, atgrieztais rezultāts tiek pārbaudīts un rezultāts būs "Datubāzē nav ieraksta", tomēr praksē izrādās savādāk un izpildot šādu kodu iegūst SqlNullValueException. Izrādās, ka gadījumos, kad no datubāzes var tikt atgriezta NULL vērtība, ir jāpārbauda īpašība IsNull, kura tad arī norāda, vai mainīgais satur kādu vērtību. No vienas puses vienkārši, no otras - ir redzēti gadījumi, kad izstrādātāji uz šo ir "iekrituši".

Tiem, kam mans apraksts liekas nesaprotams - lai runā kods:

using System;
using System.Data.SqlTypes;

namespace NullableDemo
{
    class Example
    {
        private SqlGuid _guid = new SqlGuid();

        /// <summary>
        /// Gets the property wrong.
        /// </summary>
        /// <value>Exception :)</value>
        public Guid? PropertyWrong
        {
            get { return _guid.Value; }
        }

        /// <summary>
        /// Gets the property right.
        /// </summary>
        /// <value>null</value>
        public Guid? PropertyRight
        {
            get
            {
                if (_guid.IsNull)
                    return null;

                return _guid.Value;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Example example = new Example();
            try
            {
                Console.WriteLine("Right way:");
                Guid guid = example.PropertyRight ?? Guid.Empty;
                Console.WriteLine(guid);

                Console.WriteLine("Wrong way:");
                guid = example.PropertyWrong ?? Guid.Empty;
                Console.WriteLine(guid);
            }
            catch (SqlNullValueException e)
            {
                Console.WriteLine("Exception:");
                Console.WriteLine(e.Message);
            }
        }
    }
}

Un ekrānšāviņš:

Nullable_demo_output


*How to shoot yourself in the foot links:

Līniju numuri

Labrīt!

Iespējams, ka arī Tu reizēm lieto kādu no Microsoft Visual Studio Express komplektiem. Es, piemēram, mēdzu izmantot C# 2008 Express Edition un kādu laiku man nācās samierināties ar Problēmu. Problēma savā būtībā ir pavisam vienkārša un triviāla - nevarēju ieslēgt līniju numuru attēlošanu teksta redaktorā.

Lai gan zināju, ka ieslēgšanai būtu jābūt ķeksim Tools -> Options -> Text Editor -> All Languages (vai C#), tā tur nebija.

Options window (default)

Par spīti tam, ka Problēma sagādāja zināmu diskomfortu, neredzēju tai risinājumu, tāpēc kādu laiku to atstāju mierā. Dažādu apstākļu sakritību rezultātā, šorīt gadījās vēlreiz atvērt opciju logu, un pirmā lieta, ko pamanīju, bija ķeksis Show all settings. Ieķeksēju un Voila!!!! Problēmas risinājums ir atrasts!

Options window (all settings)

Sveikiņi, jeb kā es beidzu uztraukties un iemīlēju Windows Live Writer.

Sveiki, kolēģi!

Nupat esmu pievienojies .NET lietotāju grupas emuāristiem/blogeriem un satraukuma pilns vēlos ar Jums padalīties informācijā, kā sakonfigurēt Windows Live Writer darbam ar dotnet.lv blogiem.

Sākumā protams šis produkts ir jāuzinstalē. Tā kā šobrīd izskatās, ka oficiālā vietne ir "noliekusies", tad atļaušos norādīt uz tiešo atrašanās vietu. (upd: Biju palaidis garām to, ka ir iznākusi final versija, kuru var atrast šeit.) Instalācijas process ir pietiekami vienkāršs, lai neiedziļinātos sīkākā aprakstā.

Tālāk ir galvenais - konfigurācija. Manuprāt, pie pirmās palaišanas automātiski parādījās konfigurācijas vednis, bet, ja nu gadījumā tā nav, pie tā var nokļūt arī no izvēlnes "Weblog" izvēloties punktu "Add Weblog account...".

Sākotnēji mums laipni tiek piedāvāts izvēlēties bloga tipu. Mūsu gadījumā tas ir "Another weblog service".

 

Nākošais solis jau ir sarežģītāks, jo tur nepietiek ar ķeksīša pareizu izvēli, bet nepieciešams datus ierakstīt ar rociņām. Norādāmie dati - blogu URL (http://dotnet.lv/blogs), lietotāja vārds un parole. Nekāda raķešu zinātne, bet vēlams atcerēties, ka URL ir jāievada blogiem nevis konkrētajam blogam.

  

Turpinam ar tādiem pašiem vidējas sarežģītības soļiem. Solis trīs no mums prasa izvēlēties bloga tipu (tiem, kas tankā: Community server) un ieejas punkta URL (http://dotnet.lv/blogs/metablog.ashx).

Tālāk nedaudz uzgaidam, kamēr tiek ielādēta informācija par blogu un tā stils (lai varētu pirms publicēšanas redzēt, kā izskatīsies ieraksts.

Nu un tad paliek tāds sīkums kā ierakstīt bloga konta nosaukumu (vai atstāt noklusēto).

Un varam sākt rakstīt...

 

Tas arī viss, veiksmi rakstu radīšanā!